

<!DOCTYPE html>
<html lang="zh-CN" data-default-color-scheme=&#34;auto&#34;>



<head>
  <meta charset="UTF-8">
  <link rel="apple-touch-icon" sizes="76x76" href="/img/favicon.png">
  <link rel="icon" type="image/png" href="/img/favicon.png">
  <meta name="viewport"
        content="width=device-width, initial-scale=1.0, maximum-scale=1.0, user-scalable=no, shrink-to-fit=no">
  <meta http-equiv="x-ua-compatible" content="ie=edge">
  
  <meta name="theme-color" content="#2f4154">
  <meta name="description" content="">
  <meta name="author" content="caoyusang">
  <meta name="keywords" content="">
  <title>TX笔试 - caoyusang的科研日常</title>

  <link  rel="stylesheet" href="https://cdn.staticfile.org/twitter-bootstrap/4.4.1/css/bootstrap.min.css" />


  <link  rel="stylesheet" href="https://cdn.staticfile.org/github-markdown-css/4.0.0/github-markdown.min.css" />
  <link  rel="stylesheet" href="/lib/hint/hint.min.css" />

  
    
    
      
      <link  rel="stylesheet" href="https://cdn.staticfile.org/highlight.js/10.0.0/styles/github-gist.min.css" />
    
  

  


<!-- 主题依赖的图标库，不要自行修改 -->

<link rel="stylesheet" href="//at.alicdn.com/t/font_1749284_ba1fz6golrf.css">



<link rel="stylesheet" href="//at.alicdn.com/t/font_1736178_kmeydafke9r.css">


<link  rel="stylesheet" href="/css/main.css" />

<!-- 自定义样式保持在最底部 -->


  <script  src="/js/utils.js" ></script>
  <script  src="/js/color-schema.js" ></script>
<meta name="generator" content="Hexo 5.2.0"></head>


<body>
  <header style="height: 70vh;">
    <nav id="navbar" class="navbar fixed-top  navbar-expand-lg navbar-dark scrolling-navbar">
  <div class="container">
    <a class="navbar-brand"
       href="/">&nbsp;<strong>caoyusang</strong>&nbsp;</a>

    <button id="navbar-toggler-btn" class="navbar-toggler" type="button" data-toggle="collapse"
            data-target="#navbarSupportedContent"
            aria-controls="navbarSupportedContent" aria-expanded="false" aria-label="Toggle navigation">
      <div class="animated-icon"><span></span><span></span><span></span></div>
    </button>

    <!-- Collapsible content -->
    <div class="collapse navbar-collapse" id="navbarSupportedContent">
      <ul class="navbar-nav ml-auto text-center">
        
          
          
          
          
            <li class="nav-item">
              <a class="nav-link" href="/">
                <i class="iconfont icon-home-fill"></i>
                首页
              </a>
            </li>
          
        
          
          
          
          
            <li class="nav-item">
              <a class="nav-link" href="/archives/">
                <i class="iconfont icon-archive-fill"></i>
                归档
              </a>
            </li>
          
        
          
          
          
          
            <li class="nav-item">
              <a class="nav-link" href="/categories/">
                <i class="iconfont icon-category-fill"></i>
                分类
              </a>
            </li>
          
        
          
          
          
          
            <li class="nav-item">
              <a class="nav-link" href="/tags/">
                <i class="iconfont icon-tags-fill"></i>
                标签
              </a>
            </li>
          
        
          
          
          
          
            <li class="nav-item">
              <a class="nav-link" href="/about/">
                <i class="iconfont icon-user-fill"></i>
                关于
              </a>
            </li>
          
        
        
          <li class="nav-item" id="search-btn">
            <a class="nav-link" data-toggle="modal" data-target="#modalSearch">&nbsp;<i
                class="iconfont icon-search"></i>&nbsp;</a>
          </li>
        
        
          <li class="nav-item" id="color-toggle-btn">
            <a class="nav-link" href="javascript:">&nbsp;<i
                class="iconfont icon-dark" id="color-toggle-icon"></i>&nbsp;</a>
          </li>
        
      </ul>
    </div>
  </div>
</nav>

    <div class="banner intro-2" id="background" parallax=true
         style="background: url('/img/7.jpg') no-repeat center center;
           background-size: cover;">
      <div class="full-bg-img">
        <div class="mask flex-center" style="background-color: rgba(0, 0, 0, 0.3)">
          <div class="container page-header text-center fade-in-up">
            <span class="h2" id="subtitle">
              
            </span>

            
              <div class="mt-3">
  
  
    <span class="post-meta">
      <i class="iconfont icon-date-fill" aria-hidden="true"></i>
      <time datetime="2021-05-03 16:06" pubdate>
        2021年5月3日 下午
      </time>
    </span>
  
</div>

<div class="mt-1">
  
    
    <span class="post-meta mr-2">
      <i class="iconfont icon-chart"></i>
      22.5k 字
    </span>
  

  
    
    <span class="post-meta mr-2">
      <i class="iconfont icon-clock-fill"></i>
      
      
      423
       分钟
    </span>
  

  
  
    
      <!-- 不蒜子统计文章PV -->
      <span id="busuanzi_container_page_pv" style="display: none">
        <i class="iconfont icon-eye" aria-hidden="true"></i>
        <span id="busuanzi_value_page_pv"></span> 次
      </span>
    
  
</div>

            
          </div>

          
        </div>
      </div>
    </div>
  </header>

  <main>
    
      

<div class="container-fluid">
  <div class="row">
    <div class="d-none d-lg-block col-lg-2"></div>
    <div class="col-lg-8 nopadding-md">
      <div class="container nopadding-md" id="board-ctn">
        <div class="py-5" id="board">
          <article class="post-content mx-auto" id="post">
            <!-- SEO header -->
            <h1 style="display: none">TX笔试</h1>
            
              <p class="note note-info">
                
                  本文最后更新于：25 天前
                
              </p>
            
            <div class="markdown-body" id="post-body">
              <h2 id="206-反转链表"><a href="#206-反转链表" class="headerlink" title="206-反转链表"></a>206-反转链表</h2><p><code>头插法</code></p>
<pre><code class="hljs java"><span class="hljs-comment">/**</span>
<span class="hljs-comment"> * Definition for singly-linked list.</span>
<span class="hljs-comment"> * public class ListNode &#123;</span>
<span class="hljs-comment"> *     int val;</span>
<span class="hljs-comment"> *     ListNode next;</span>
<span class="hljs-comment"> *     ListNode(int x) &#123; val = x; &#125;</span>
<span class="hljs-comment"> * &#125;</span>
<span class="hljs-comment"> */</span>
<span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">Solution</span> </span>&#123;
    <span class="hljs-function"><span class="hljs-keyword">public</span> ListNode <span class="hljs-title">reverseList</span><span class="hljs-params">(ListNode head)</span> </span>&#123;
        <span class="hljs-comment">//结果链表的表头</span>
        ListNode pre = <span class="hljs-keyword">new</span> ListNode(-<span class="hljs-number">1</span>);
        <span class="hljs-comment">//链表尾部置null</span>
        pre.next = <span class="hljs-keyword">null</span>;
        
        <span class="hljs-comment">//头插法</span>
        <span class="hljs-keyword">while</span> (head != <span class="hljs-keyword">null</span>)&#123;
            <span class="hljs-comment">//先把插入位置后一个节点记录下来</span>
            ListNode temp = pre.next;
            <span class="hljs-comment">//遍历到的节点接到pre的后面</span>
            ListNode ist = <span class="hljs-keyword">new</span> ListNode(head.val);
            pre.next = ist;
            <span class="hljs-comment">//把尾部也接上</span>
            ist.next = temp;
            <span class="hljs-comment">//遍历原链表</span>
            head = head.next;
        &#125;
        <span class="hljs-comment">//返回结果链表</span>
        <span class="hljs-keyword">return</span> pre.next;
    &#125;
&#125;
</code></pre>
<p><code>扭一扭</code></p>
<img src="/2021/05/03/TX%E7%AC%94%E8%AF%95/image-20210318164102494.png" srcset="/img/loading.gif" class="">
<pre><code class="hljs java"><span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">Solution</span> </span>&#123;
    <span class="hljs-function"><span class="hljs-keyword">public</span> ListNode <span class="hljs-title">reverseList</span><span class="hljs-params">(ListNode head)</span> </span>&#123;
        ListNode pre = <span class="hljs-keyword">new</span> ListNode(<span class="hljs-number">0</span>);
        pre.next = head;
        ListNode p = head;
        <span class="hljs-keyword">while</span> (p != <span class="hljs-keyword">null</span> &amp;&amp; p.next != <span class="hljs-keyword">null</span>)&#123;
            ListNode tmp = pre.next;
            pre.next = p.next;
            p.next = p.next.next;
            pre.next.next = tmp;
        &#125;
        <span class="hljs-keyword">return</span> pre.next;
    &#125;
&#125;</code></pre>
<h2 id="148-排序链表"><a href="#148-排序链表" class="headerlink" title="148-排序链表"></a>148-排序链表</h2><p>给你链表的头结点 head ，请将其按升序排列并返回排序后的链表 。</p>
<p><code>进阶</code>：</p>
<p>你可以在 O(n log n) 时间复杂度和常数级空间复杂度下，对链表进行排序吗？</p>
<img src="/2021/05/03/TX%E7%AC%94%E8%AF%95/image-20210329091852105.png" srcset="/img/loading.gif" class="">
<p><code>归并排序 + 快慢指针</code></p>
<pre><code class="hljs java"><span class="hljs-comment">/**</span>
<span class="hljs-comment"> * Definition for singly-linked list.</span>
<span class="hljs-comment"> * public class ListNode &#123;</span>
<span class="hljs-comment"> *     int val;</span>
<span class="hljs-comment"> *     ListNode next;</span>
<span class="hljs-comment"> *     ListNode() &#123;&#125;</span>
<span class="hljs-comment"> *     ListNode(int val) &#123; this.val = val; &#125;</span>
<span class="hljs-comment"> *     ListNode(int val, ListNode next) &#123; this.val = val; this.next = next; &#125;</span>
<span class="hljs-comment"> * &#125;</span>
<span class="hljs-comment"> */</span>
<span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">Solution</span> </span>&#123;
    <span class="hljs-comment">//归并排序O(NlogN)</span>
    <span class="hljs-function"><span class="hljs-keyword">public</span> ListNode <span class="hljs-title">sortList</span><span class="hljs-params">(ListNode head)</span> </span>&#123;
        <span class="hljs-comment">//归并排序</span>
        <span class="hljs-keyword">if</span> (head == <span class="hljs-keyword">null</span> || head.next == <span class="hljs-keyword">null</span>) <span class="hljs-keyword">return</span> head;
        <span class="hljs-comment">//快慢指针找中间节点</span>
        ListNode slowPtr = head, fastPtr = head.next;
        <span class="hljs-keyword">while</span> (fastPtr != <span class="hljs-keyword">null</span> &amp;&amp; fastPtr.next != <span class="hljs-keyword">null</span>)&#123;
            fastPtr = fastPtr.next.next;
            slowPtr = slowPtr.next;
        &#125;
        <span class="hljs-comment">//记录后半部分链表的表头指针</span>
        ListNode lastHalf = slowPtr.next;
        <span class="hljs-comment">//将slowPtr所在位置后面的链表全部断开</span>
        slowPtr.next = <span class="hljs-keyword">null</span>;

        <span class="hljs-comment">//递归</span>
        ListNode leftHalf = sortList(head);
        ListNode rightHalf = sortList(lastHalf);
        <span class="hljs-keyword">return</span> merge(leftHalf, rightHalf);
    &#125;

    <span class="hljs-function"><span class="hljs-keyword">public</span> ListNode <span class="hljs-title">merge</span><span class="hljs-params">(ListNode p, ListNode q)</span></span>&#123;
        ListNode res = <span class="hljs-keyword">new</span> ListNode(<span class="hljs-number">0</span>);
        ListNode pre = res;
        <span class="hljs-keyword">while</span> (p != <span class="hljs-keyword">null</span> &amp;&amp; q != <span class="hljs-keyword">null</span>)&#123;
            <span class="hljs-keyword">if</span> (p.val &lt;= q.val)&#123;
                pre.next = p;
                p = p.next;
            &#125; <span class="hljs-keyword">else</span> &#123;
                pre.next = q;
                q = q.next;
            &#125;
            pre = pre.next;
        &#125;
        pre.next = p != <span class="hljs-keyword">null</span> ? p : q;

        <span class="hljs-keyword">return</span> res.next;
    &#125;
&#125;</code></pre>
<h2 id="剑指Offer54-二叉搜索树的第k大节点"><a href="#剑指Offer54-二叉搜索树的第k大节点" class="headerlink" title="剑指Offer54-二叉搜索树的第k大节点"></a>剑指Offer54-二叉搜索树的第k大节点</h2><p>给定一棵二叉搜索树，请找出其中第k大的节点。</p>
<p><code>改造中序遍历即可</code></p>
<pre><code class="hljs java"><span class="hljs-comment">/**</span>
<span class="hljs-comment"> * Definition for a binary tree node.</span>
<span class="hljs-comment"> * public class TreeNode &#123;</span>
<span class="hljs-comment"> *     int val;</span>
<span class="hljs-comment"> *     TreeNode left;</span>
<span class="hljs-comment"> *     TreeNode right;</span>
<span class="hljs-comment"> *     TreeNode(int x) &#123; val = x; &#125;</span>
<span class="hljs-comment"> * &#125;</span>
<span class="hljs-comment"> */</span>
<span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">Solution</span> </span>&#123;
    <span class="hljs-keyword">int</span> res = <span class="hljs-number">0</span>;
    <span class="hljs-keyword">int</span> cnt = <span class="hljs-number">0</span>;
    <span class="hljs-function"><span class="hljs-keyword">public</span> <span class="hljs-keyword">int</span> <span class="hljs-title">kthLargest</span><span class="hljs-params">(TreeNode root, <span class="hljs-keyword">int</span> k)</span> </span>&#123;
        <span class="hljs-keyword">this</span>.cnt = k;
        inorderReverse(root);
        <span class="hljs-keyword">return</span> res;
    &#125;

    <span class="hljs-function"><span class="hljs-keyword">public</span> <span class="hljs-keyword">void</span> <span class="hljs-title">inorderReverse</span><span class="hljs-params">(TreeNode node)</span></span>&#123;
        <span class="hljs-keyword">if</span> (node == <span class="hljs-keyword">null</span>) <span class="hljs-keyword">return</span>;
        <span class="hljs-comment">//先访问右节点</span>
        <span class="hljs-keyword">if</span> (node.right != <span class="hljs-keyword">null</span>)&#123;
            inorderReverse(node.right);
        &#125;
        <span class="hljs-comment">//cnt==0说明已经对res赋予了第k大的值，可以返回</span>
        <span class="hljs-keyword">if</span> (cnt == <span class="hljs-number">0</span>) <span class="hljs-keyword">return</span>;
        <span class="hljs-comment">//对res赋值</span>
        <span class="hljs-keyword">if</span> (--cnt == <span class="hljs-number">0</span>)&#123;
            res = node.val;
        &#125;
        <span class="hljs-comment">//访问左节点</span>
        <span class="hljs-keyword">if</span> (node.left != <span class="hljs-keyword">null</span>)&#123;
            inorderReverse(node.left);
        &#125;
    &#125;
&#125;</code></pre>
<h2 id="3-无重复字符的最长连续子串"><a href="#3-无重复字符的最长连续子串" class="headerlink" title="3-无重复字符的最长连续子串"></a>3-无重复字符的最长连续子串</h2><p>给定一个字符串，请你找出其中不含有重复字符的 <strong>最长子串</strong>的长度。</p>
<p><code>HashMap + 双指针</code></p>
<pre><code class="hljs java"><span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">Solution</span> </span>&#123;
    <span class="hljs-function"><span class="hljs-keyword">public</span> <span class="hljs-keyword">int</span> <span class="hljs-title">lengthOfLongestSubstring</span><span class="hljs-params">(String s)</span> </span>&#123;
        <span class="hljs-keyword">int</span> n = s.length();
        <span class="hljs-comment">//字符串长度小于等于1的情况直接返回长度</span>
        <span class="hljs-keyword">if</span> (n &lt;= <span class="hljs-number">1</span>) <span class="hljs-keyword">return</span> n;
        HashMap&lt;Character, Integer&gt; map = <span class="hljs-keyword">new</span> HashMap&lt;&gt;();
        <span class="hljs-keyword">int</span> left = <span class="hljs-number">0</span>, right = <span class="hljs-number">0</span>, maxLen = Integer.MIN_VALUE;
        <span class="hljs-keyword">while</span> (right &lt; n)&#123;
            <span class="hljs-keyword">char</span> tmp = s.charAt(right);  
            map.put(tmp, map.getOrDefault(tmp, <span class="hljs-number">0</span>) + <span class="hljs-number">1</span>);
            <span class="hljs-keyword">while</span> (map.get(tmp) &gt; <span class="hljs-number">1</span>)&#123;
                <span class="hljs-keyword">char</span> d = s.charAt(left);
                left++;
                <span class="hljs-comment">//收缩窗口，计数减1</span>
                map.put(d, map.get(d) - <span class="hljs-number">1</span>);
            &#125;
            <span class="hljs-comment">//循环更新最大长度</span>
            maxLen = Math.max(maxLen, right - left + <span class="hljs-number">1</span>);
            right++;          

        &#125;
        <span class="hljs-keyword">return</span> maxLen;
    &#125;
&#125;</code></pre>
<h2 id="300-最长递增子序列"><a href="#300-最长递增子序列" class="headerlink" title="300-最长递增子序列"></a>300-最长递增子序列</h2><p>给你一个整数数组 nums ，找到其中最长严格递增子序列的长度。</p>
<p>子序列是由数组派生而来的序列，删除（或不删除）数组中的元素而不改变其余元素的顺序。例如，[3,6,2,7] 是数组 [0,3,1,6,2,2,7] 的子序列。</p>
<pre><code class="hljs java"><span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">Solution</span> </span>&#123;
    <span class="hljs-function"><span class="hljs-keyword">public</span> <span class="hljs-keyword">int</span> <span class="hljs-title">lengthOfLIS</span><span class="hljs-params">(<span class="hljs-keyword">int</span>[] nums)</span> </span>&#123;
        <span class="hljs-keyword">int</span> n = nums.length;
        <span class="hljs-comment">//动态规划，dp[i]代表以nums[i]结尾的严格递增子序列的最长长度</span>
        <span class="hljs-keyword">int</span>[] dp = <span class="hljs-keyword">new</span> <span class="hljs-keyword">int</span>[n];
        Arrays.fill(dp, <span class="hljs-number">1</span>);
        <span class="hljs-keyword">for</span> (<span class="hljs-keyword">int</span> i = <span class="hljs-number">0</span>; i &lt; n; i++)&#123;
            <span class="hljs-keyword">for</span> (<span class="hljs-keyword">int</span> j = <span class="hljs-number">0</span>; j &lt; i; j++)&#123;
                <span class="hljs-comment">//状态更新</span>
                <span class="hljs-keyword">if</span> (nums[j] &lt; nums[i])&#123;
                    dp[i] = Math.max(dp[i], dp[j] + <span class="hljs-number">1</span>);
                &#125;
            &#125;
        &#125;
        <span class="hljs-keyword">int</span> maxLen = Integer.MIN_VALUE;
        <span class="hljs-keyword">for</span> (<span class="hljs-keyword">int</span> len : dp)&#123;
            maxLen = Math.max(maxLen, len);
        &#125;
        <span class="hljs-keyword">return</span> maxLen;
    &#125;
&#125;</code></pre>
<h2 id="2-两数相加"><a href="#2-两数相加" class="headerlink" title="2-两数相加"></a>2-两数相加</h2><p>给你两个非空的链表，表示两个非负的整数。它们每位数字都是按照 逆序 的方式存储的，并且每个节点只能存储一位数字。</p>
<p>请你将两个数相加，并以相同形式返回一个表示和的链表。</p>
<img src="/2021/05/03/TX%E7%AC%94%E8%AF%95/image-20210318152945850.png" srcset="/img/loading.gif" class="">
<pre><code class="hljs java"><span class="hljs-comment">/**</span>
<span class="hljs-comment"> * Definition for singly-linked list.</span>
<span class="hljs-comment"> * public class ListNode &#123;</span>
<span class="hljs-comment"> *     int val;</span>
<span class="hljs-comment"> *     ListNode next;</span>
<span class="hljs-comment"> *     ListNode() &#123;&#125;</span>
<span class="hljs-comment"> *     ListNode(int val) &#123; this.val = val; &#125;</span>
<span class="hljs-comment"> *     ListNode(int val, ListNode next) &#123; this.val = val; this.next = next; &#125;</span>
<span class="hljs-comment"> * &#125;</span>
<span class="hljs-comment"> */</span>
<span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">Solution</span> </span>&#123;
    <span class="hljs-function"><span class="hljs-keyword">public</span> ListNode <span class="hljs-title">addTwoNumbers</span><span class="hljs-params">(ListNode l1, ListNode l2)</span> </span>&#123;
        <span class="hljs-comment">//结果指针</span>
        ListNode p = <span class="hljs-keyword">new</span> ListNode(<span class="hljs-number">0</span>);
        ListNode p1 = l1, p2 = l2, q = p;
        <span class="hljs-comment">//进位初始化</span>
        <span class="hljs-keyword">int</span> add = <span class="hljs-number">0</span>;
        <span class="hljs-comment">//两个链表必须全部到底才能完成之前位上的加法</span>
        <span class="hljs-keyword">while</span> (p1 != <span class="hljs-keyword">null</span> || p2 != <span class="hljs-keyword">null</span>)&#123;
            <span class="hljs-keyword">int</span> sum = add;
            <span class="hljs-keyword">if</span> (p1 != <span class="hljs-keyword">null</span>)&#123;
                sum += p1.val;
                p1 = p1.next;
            &#125; 
            <span class="hljs-keyword">if</span> (p2 != <span class="hljs-keyword">null</span>)&#123;
                sum += p2.val;
                p2 = p2.next;
            &#125;
            <span class="hljs-comment">//进位更新</span>
            add = sum / <span class="hljs-number">10</span>;
            p.next = <span class="hljs-keyword">new</span> ListNode(sum % <span class="hljs-number">10</span>);
            p = p.next;
        &#125;
        <span class="hljs-comment">//还有进位，则直接在末尾添上节点1</span>
        <span class="hljs-keyword">if</span> (add != <span class="hljs-number">0</span>)&#123;
            p.next = <span class="hljs-keyword">new</span> ListNode(<span class="hljs-number">1</span>);
        &#125;
        <span class="hljs-comment">//返回之前暂存的结果指针后面的节点</span>
        <span class="hljs-keyword">return</span> q.next;
    &#125;
&#125;</code></pre>
<h2 id="25-K个一组翻转链表"><a href="#25-K个一组翻转链表" class="headerlink" title="25-K个一组翻转链表"></a>25-K个一组翻转链表</h2><p>给你一个链表，每 k 个节点一组进行翻转，请你返回翻转后的链表。</p>
<p>k 是一个正整数，它的值小于或等于链表的长度。</p>
<p>如果节点总数不是 k 的整数倍，那么请将最后剩余的节点<code>保持原有顺序</code>。</p>
<p><code>进阶</code>：</p>
<p>你可以设计一个只使用<code>常数额外空间</code>的算法来解决此问题吗？你不能只是单纯的改变节点内部的值，而是需要实际进行节点交换</p>
<img src="/2021/05/03/TX%E7%AC%94%E8%AF%95/image-20210318155055481.png" srcset="/img/loading.gif" class="">
<pre><code class="hljs java"><span class="hljs-comment">/**</span>
<span class="hljs-comment"> * Definition for singly-linked list.</span>
<span class="hljs-comment"> * public class ListNode &#123;</span>
<span class="hljs-comment"> *     int val;</span>
<span class="hljs-comment"> *     ListNode next;</span>
<span class="hljs-comment"> *     ListNode() &#123;&#125;</span>
<span class="hljs-comment"> *     ListNode(int val) &#123; this.val = val; &#125;</span>
<span class="hljs-comment"> *     ListNode(int val, ListNode next) &#123; this.val = val; this.next = next; &#125;</span>
<span class="hljs-comment"> * &#125;</span>
<span class="hljs-comment"> */</span>
<span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">Solution</span> </span>&#123;
    <span class="hljs-function"><span class="hljs-keyword">public</span> ListNode <span class="hljs-title">reverseKGroup</span><span class="hljs-params">(ListNode head, <span class="hljs-keyword">int</span> k)</span> </span>&#123;
        ListNode pre = <span class="hljs-keyword">new</span> ListNode(<span class="hljs-number">0</span>);
        <span class="hljs-comment">//记录结果指针</span>
        ListNode res = pre;
        pre.next = head;
        ListNode p = head, q = head;
        <span class="hljs-keyword">int</span> listLen = <span class="hljs-number">0</span>;
        <span class="hljs-comment">//得到链表长度</span>
        <span class="hljs-keyword">while</span> (q != <span class="hljs-keyword">null</span>)&#123;
            q = q.next;
            listLen++;
        &#125;
        <span class="hljs-comment">//得到需要翻转的链表的组数</span>
        <span class="hljs-keyword">int</span> groupNum = listLen / k;
        
        <span class="hljs-keyword">while</span> (groupNum-- &gt; <span class="hljs-number">0</span>)&#123;
            <span class="hljs-keyword">int</span> cnt = <span class="hljs-number">0</span>;
            <span class="hljs-keyword">while</span> (p != <span class="hljs-keyword">null</span> &amp;&amp; p.next != <span class="hljs-keyword">null</span> &amp;&amp; ++cnt &lt; k)&#123;
                ListNode tmp = pre.next;
                pre.next = p.next;
                p.next = p.next.next;
                pre.next.next = tmp;
            &#125;
            <span class="hljs-comment">//重置链表开始翻转的位置</span>
            pre = p;
            p = p.next;
        &#125;
        <span class="hljs-keyword">return</span> res.next;
        
        
    &#125;
&#125;</code></pre>
<h2 id="42-接雨水"><a href="#42-接雨水" class="headerlink" title="42-接雨水"></a>42-接雨水</h2><p>给定 <em>n</em> 个非负整数表示每个宽度为 1 的柱子的高度图，计算按此排列的柱子，下雨之后能接多少雨水。</p>
<img src="/2021/05/03/TX%E7%AC%94%E8%AF%95/image-20210319094640704.png" srcset="/img/loading.gif" class="">
<p><code>按列计算的普通解法</code>——某列能存水的数目等于左右两侧最高处中的最小值(比该列高)减去该列的高度</p>
<img src="/2021/05/03/TX%E7%AC%94%E8%AF%95/image-20210319100446457.png" srcset="/img/loading.gif" class="">
<pre><code class="hljs java"><span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">Solution</span> </span>&#123;
    <span class="hljs-function"><span class="hljs-keyword">public</span> <span class="hljs-keyword">int</span> <span class="hljs-title">trap</span><span class="hljs-params">(<span class="hljs-keyword">int</span>[] height)</span> </span>&#123;
		<span class="hljs-comment">//按列的普通解法O(n^2)</span>
        <span class="hljs-keyword">int</span> n = height.length;
        <span class="hljs-keyword">int</span> res = <span class="hljs-number">0</span>;
        <span class="hljs-comment">//第一个位置和最后一个位置肯定存不了水，所以掐头去尾</span>
        <span class="hljs-keyword">for</span> (<span class="hljs-keyword">int</span> i = <span class="hljs-number">1</span>; i &lt; n - <span class="hljs-number">1</span>; i++)&#123;
            <span class="hljs-keyword">int</span> maxLeft = Integer.MIN_VALUE, maxRight = Integer.MIN_VALUE;
            <span class="hljs-comment">//找左侧最高</span>
            <span class="hljs-keyword">for</span> (<span class="hljs-keyword">int</span> j = i - <span class="hljs-number">1</span>; j &gt;= <span class="hljs-number">0</span>; j--)&#123;
                maxLeft = Math.max(maxLeft, height[j]);
            &#125;
            <span class="hljs-comment">//找右侧最高</span>
            <span class="hljs-keyword">for</span> (<span class="hljs-keyword">int</span> j = i + <span class="hljs-number">1</span>; j &lt; n; j++)&#123;
                maxRight = Math.max(maxRight, height[j]);
            &#125;
            <span class="hljs-keyword">int</span> minHeight = Math.min(maxLeft, maxRight);
            <span class="hljs-comment">//两边的最高柱一定要比当前位置高度高才能存水</span>
            <span class="hljs-keyword">if</span> (minHeight &gt; height[i])&#123;
                <span class="hljs-comment">//第i个位置能盛多少容积的水？ —— 位置i的左右两侧柱子的最高高度中的最小值减去自身高度</span>
                res += (minHeight - height[i]);
            &#125;

        &#125;
        <span class="hljs-keyword">return</span> res;
    &#125;
&#125;</code></pre>
<p><code>动态规划</code>——空间换时间，在进行按列遍历前就求好左右两侧最高柱的高度O(N^2)-&gt;O(2*N)</p>
<pre><code class="hljs java"><span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">Solution</span> </span>&#123;
    <span class="hljs-function"><span class="hljs-keyword">public</span> <span class="hljs-keyword">int</span> <span class="hljs-title">trap</span><span class="hljs-params">(<span class="hljs-keyword">int</span>[] height)</span> </span>&#123;
		<span class="hljs-comment">//动态规划，空间换时间，事先就求好位置i左右两侧的最高柱的高度</span>
        <span class="hljs-keyword">int</span> n = height.length;
        <span class="hljs-keyword">int</span> res = <span class="hljs-number">0</span>;
        <span class="hljs-keyword">int</span>[] maxLeft = <span class="hljs-keyword">new</span> <span class="hljs-keyword">int</span>[n];
        <span class="hljs-keyword">int</span>[] maxRight = <span class="hljs-keyword">new</span> <span class="hljs-keyword">int</span>[n];

        <span class="hljs-comment">//左侧</span>
        <span class="hljs-keyword">for</span> (<span class="hljs-keyword">int</span> i = <span class="hljs-number">1</span>; i &lt; n - <span class="hljs-number">1</span>; i++)&#123;
            maxLeft[i] = Math.max(maxLeft[i - <span class="hljs-number">1</span>] , height[i - <span class="hljs-number">1</span>]);
        &#125;

        <span class="hljs-comment">//右侧</span>
        <span class="hljs-keyword">for</span> (<span class="hljs-keyword">int</span> i = n - <span class="hljs-number">2</span>; i &gt;= <span class="hljs-number">1</span>; i--)&#123;
            maxRight[i] = Math.max(maxRight[i + <span class="hljs-number">1</span>], height[i + <span class="hljs-number">1</span>]);
        &#125;

        <span class="hljs-keyword">for</span> (<span class="hljs-keyword">int</span> i = <span class="hljs-number">1</span>; i &lt; n - <span class="hljs-number">1</span>; i++)&#123;
            <span class="hljs-keyword">int</span> minHeight = Math.min(maxLeft[i], maxRight[i]);
            <span class="hljs-keyword">if</span> (minHeight &gt; height[i])&#123;
                <span class="hljs-comment">//第i个位置能盛多少容积的水？ —— 位置i的左右两侧柱子的最高高度中的最小值减去自身高度</span>
                res += (minHeight - height[i]);
            &#125;
        &#125;
        <span class="hljs-keyword">return</span> res;
    &#125;
&#125;</code></pre>
<p><code>双指针 + 动态规划</code>：时O(N)，空O(1)</p>
<pre><code class="hljs java"><span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">Solution</span> </span>&#123;
    <span class="hljs-function"><span class="hljs-keyword">public</span> <span class="hljs-keyword">int</span> <span class="hljs-title">trap</span><span class="hljs-params">(<span class="hljs-keyword">int</span>[] height)</span> </span>&#123;
		<span class="hljs-comment">//双指针 + 动态规划，时O(N) , 空O(1)</span>
        <span class="hljs-keyword">int</span> n = height.length;
        <span class="hljs-keyword">int</span> res = <span class="hljs-number">0</span>;
        <span class="hljs-keyword">int</span> left = <span class="hljs-number">0</span>, right = n - <span class="hljs-number">1</span>;
        <span class="hljs-comment">//分别存储左右两侧的最高值</span>
        <span class="hljs-keyword">int</span> leftMax = <span class="hljs-number">0</span>, rightMax = <span class="hljs-number">0</span>;
        <span class="hljs-comment">//双指针对象遍历</span>
        <span class="hljs-keyword">while</span> (left &lt; right)&#123;
		   <span class="hljs-comment">//保证当前列是和左右两侧最低的比</span>
            <span class="hljs-keyword">if</span> (height[left] &lt; height[right])&#123;
                <span class="hljs-comment">//比左边最高还要高，存不了水，更新左侧最高值即可</span>
                <span class="hljs-keyword">if</span> (height[left] &gt;= leftMax)&#123;
                    leftMax = height[left];
                &#125;<span class="hljs-keyword">else</span> &#123;	<span class="hljs-comment">//将当前列能存储的水累加到res</span>
                    res += (leftMax - height[left]);
                &#125;
                <span class="hljs-comment">//左指针右移</span>
                left++;
            &#125; <span class="hljs-keyword">else</span> &#123;	<span class="hljs-comment">//若右侧较低时，同理</span>
                <span class="hljs-keyword">if</span> (height[right] &gt;= rightMax)&#123;
                    rightMax = height[right];
                &#125; <span class="hljs-keyword">else</span> &#123;
                    res += (rightMax - height[right]);
                &#125;
                <span class="hljs-comment">//右指针左移</span>
                right--;
            &#125;
        &#125;
        <span class="hljs-keyword">return</span> res;
    &#125;
&#125;</code></pre>
<h2 id="328-奇偶链表"><a href="#328-奇偶链表" class="headerlink" title="328-奇偶链表"></a>328-奇偶链表</h2><p>给定一个单链表，把所有的奇数节点和偶数节点分别排在一起。请注意，这里的奇数节点和偶数节点指的是节点编号的奇偶性，而不是节点的值的奇偶性。</p>
<p>请尝试使用原地算法完成。你的算法的空间复杂度应为 O(1)，时间复杂度应为 O(nodes)，nodes 为节点总数。</p>
<p><code>示例1:</code></p>
<pre><code class="hljs text">输入: 1-&gt;2-&gt;3-&gt;4-&gt;5-&gt;NULL
输出: 1-&gt;3-&gt;5-&gt;2-&gt;4-&gt;NULL</code></pre>
<p><code>图解</code></p>
<img src="/2021/05/03/TX%E7%AC%94%E8%AF%95/image-20210319103411691.png" srcset="/img/loading.gif" class="">
<pre><code class="hljs java"><span class="hljs-comment">/**</span>
<span class="hljs-comment"> * Definition for singly-linked list.</span>
<span class="hljs-comment"> * public class ListNode &#123;</span>
<span class="hljs-comment"> *     int val;</span>
<span class="hljs-comment"> *     ListNode next;</span>
<span class="hljs-comment"> *     ListNode() &#123;&#125;</span>
<span class="hljs-comment"> *     ListNode(int val) &#123; this.val = val; &#125;</span>
<span class="hljs-comment"> *     ListNode(int val, ListNode next) &#123; this.val = val; this.next = next; &#125;</span>
<span class="hljs-comment"> * &#125;</span>
<span class="hljs-comment"> */</span>
<span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">Solution</span> </span>&#123;
    <span class="hljs-function"><span class="hljs-keyword">public</span> ListNode <span class="hljs-title">oddEvenList</span><span class="hljs-params">(ListNode head)</span> </span>&#123;
        <span class="hljs-comment">//链表为空，或者只有一个节点，直接返回null或者那个唯一的节点，即head</span>
        <span class="hljs-keyword">if</span> (head == <span class="hljs-keyword">null</span> || head.next == <span class="hljs-keyword">null</span>) <span class="hljs-keyword">return</span> head;

        ListNode p = head, q = head.next, evenBegin = q;
        <span class="hljs-keyword">while</span> (q != <span class="hljs-keyword">null</span> &amp;&amp; q.next != <span class="hljs-keyword">null</span>)&#123;
            p.next = q.next;
            q.next = q.next.next;
            p = p.next;
            q = q.next;
        &#125;
        p.next = evenBegin;
        <span class="hljs-keyword">return</span> head;

    &#125;
&#125;</code></pre>
<h2 id="4-寻找两个正序数组的中位数"><a href="#4-寻找两个正序数组的中位数" class="headerlink" title="4-寻找两个正序数组的中位数"></a>4-寻找两个正序数组的中位数</h2><p>给定两个大小分别为 <code>m</code> 和 <code>n</code> 的正序（从小到大）数组 <code>nums1</code> 和 <code>nums2</code>。请你找出并返回这两个正序数组的 <strong>中位数</strong> 。</p>
<p> <code>优先权队列</code></p>
<pre><code class="hljs java"><span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">Solution</span> </span>&#123;
    <span class="hljs-function"><span class="hljs-keyword">public</span> <span class="hljs-keyword">double</span> <span class="hljs-title">findMedianSortedArrays</span><span class="hljs-params">(<span class="hljs-keyword">int</span>[] nums1, <span class="hljs-keyword">int</span>[] nums2)</span> </span>&#123;
        PriorityQueue&lt;Integer&gt; pq = <span class="hljs-keyword">new</span> PriorityQueue&lt;&gt;();
        <span class="hljs-keyword">int</span> cnt = <span class="hljs-number">0</span>;
        <span class="hljs-keyword">for</span> (<span class="hljs-keyword">int</span> num : nums1) &#123;
            pq.offer(num);
            cnt++;
        &#125;
        <span class="hljs-keyword">for</span> (<span class="hljs-keyword">int</span> num : nums2) &#123;
            pq.offer(num);
            cnt++;
        &#125;
        <span class="hljs-keyword">int</span> k = <span class="hljs-number">0</span>;
        <span class="hljs-keyword">while</span> (k &lt; cnt)&#123;
            <span class="hljs-keyword">double</span> tmp = pq.poll() * <span class="hljs-number">1.0</span>;
            <span class="hljs-keyword">if</span> (cnt % <span class="hljs-number">2</span> != <span class="hljs-number">0</span>)&#123;
                <span class="hljs-keyword">if</span> (k == cnt / <span class="hljs-number">2</span>) <span class="hljs-keyword">return</span> tmp;
            &#125;<span class="hljs-keyword">else</span> &#123;
                <span class="hljs-keyword">if</span> (k == cnt / <span class="hljs-number">2</span> - <span class="hljs-number">1</span>) <span class="hljs-keyword">return</span> (tmp + pq.poll() * <span class="hljs-number">1.0</span>) / <span class="hljs-number">2</span>;
            &#125;
            k++;
        &#125;
        <span class="hljs-keyword">return</span> -<span class="hljs-number">1.0</span>;
    &#125;
&#125;</code></pre>
<p><code>二分查找</code>  —— 不需要合并两个有序数组，只要找到中位数的位置即可。由于两个数组的长度m和n已知，因此中位数对应的两个数组的下标之和也是已知的。问题转化成寻找两个有序数组中的第 k 小的数，其中 k 为 (m+n)/2 或 (m+n)/2+1。<a target="_blank" rel="noopener" href="https://blog.csdn.net/en_joker/article/details/107179641">解法来源</a></p>
<pre><code class="hljs java"><span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">Solution</span> </span>&#123;
    <span class="hljs-function"><span class="hljs-keyword">public</span> <span class="hljs-keyword">double</span> <span class="hljs-title">findMedianSortedArrays</span><span class="hljs-params">(<span class="hljs-keyword">int</span>[] nums1, <span class="hljs-keyword">int</span>[] nums2)</span> </span>&#123;
        <span class="hljs-keyword">int</span> length1 = nums1.length, length2 = nums2.length;
        <span class="hljs-keyword">int</span> totalLength = length1 + length2;
        <span class="hljs-keyword">if</span> (totalLength % <span class="hljs-number">2</span> == <span class="hljs-number">1</span>) &#123;
            <span class="hljs-keyword">int</span> midIndex = totalLength / <span class="hljs-number">2</span>;
            <span class="hljs-keyword">double</span> median = getKthElement(nums1, nums2, midIndex + <span class="hljs-number">1</span>);
            <span class="hljs-keyword">return</span> median;
        &#125; <span class="hljs-keyword">else</span> &#123;
            <span class="hljs-keyword">int</span> midIndex1 = totalLength / <span class="hljs-number">2</span> - <span class="hljs-number">1</span>, midIndex2 = totalLength / <span class="hljs-number">2</span>;
            <span class="hljs-keyword">double</span> median = (getKthElement(nums1, nums2, midIndex1 + <span class="hljs-number">1</span>) + getKthElement(nums1, nums2, midIndex2 + <span class="hljs-number">1</span>)) / <span class="hljs-number">2.0</span>;
            <span class="hljs-keyword">return</span> median;
        &#125;
    &#125;
 
    <span class="hljs-function"><span class="hljs-keyword">public</span> <span class="hljs-keyword">int</span> <span class="hljs-title">getKthElement</span><span class="hljs-params">(<span class="hljs-keyword">int</span>[] nums1, <span class="hljs-keyword">int</span>[] nums2, <span class="hljs-keyword">int</span> k)</span> </span>&#123;
        <span class="hljs-comment">/* 主要思路：要找到第 k (k&gt;1) 小的元素，那么就取 pivot1 = nums1[k/2-1] 和 pivot2 = nums2[k/2-1] 进行比较</span>
<span class="hljs-comment">         * 这里的 &quot;/&quot; 表示整除</span>
<span class="hljs-comment">         * nums1 中小于等于 pivot1 的元素有 nums1[0 .. k/2-2] 共计 k/2-1 个</span>
<span class="hljs-comment">         * nums2 中小于等于 pivot2 的元素有 nums2[0 .. k/2-2] 共计 k/2-1 个</span>
<span class="hljs-comment">         * 取 pivot = min(pivot1, pivot2)，两个数组中小于等于 pivot 的元素共计不会超过 (k/2-1) + (k/2-1) &lt;= k-2 个</span>
<span class="hljs-comment">         * 这样 pivot 本身最大也只能是第 k-1 小的元素</span>
<span class="hljs-comment">         * 如果 pivot = pivot1，那么 nums1[0 .. k/2-1] 都不可能是第 k 小的元素。把这些元素全部 &quot;删除&quot;，剩下的作为新的 nums1 数组</span>
<span class="hljs-comment">         * 如果 pivot = pivot2，那么 nums2[0 .. k/2-1] 都不可能是第 k 小的元素。把这些元素全部 &quot;删除&quot;，剩下的作为新的 nums2 数组</span>
<span class="hljs-comment">         * 由于我们 &quot;删除&quot; 了一些元素（这些元素都比第 k 小的元素要小），因此需要修改 k 的值，减去删除的数的个数</span>
<span class="hljs-comment">         */</span>
 
        <span class="hljs-keyword">int</span> length1 = nums1.length, length2 = nums2.length;
        <span class="hljs-keyword">int</span> index1 = <span class="hljs-number">0</span>, index2 = <span class="hljs-number">0</span>;
        <span class="hljs-keyword">int</span> kthElement = <span class="hljs-number">0</span>;
 
        <span class="hljs-keyword">while</span> (<span class="hljs-keyword">true</span>) &#123;
            <span class="hljs-comment">// 边界情况</span>
            <span class="hljs-keyword">if</span> (index1 == length1) &#123;
                <span class="hljs-keyword">return</span> nums2[index2 + k - <span class="hljs-number">1</span>];
            &#125;
            <span class="hljs-keyword">if</span> (index2 == length2) &#123;
                <span class="hljs-keyword">return</span> nums1[index1 + k - <span class="hljs-number">1</span>];
            &#125;
            <span class="hljs-keyword">if</span> (k == <span class="hljs-number">1</span>) &#123;
                <span class="hljs-keyword">return</span> Math.min(nums1[index1], nums2[index2]);
            &#125;
            
            <span class="hljs-comment">// 正常情况</span>
            <span class="hljs-keyword">int</span> half = k / <span class="hljs-number">2</span>;
            <span class="hljs-keyword">int</span> newIndex1 = Math.min(index1 + half, length1) - <span class="hljs-number">1</span>;
            <span class="hljs-keyword">int</span> newIndex2 = Math.min(index2 + half, length2) - <span class="hljs-number">1</span>;
            <span class="hljs-keyword">int</span> pivot1 = nums1[newIndex1], pivot2 = nums2[newIndex2];
            <span class="hljs-keyword">if</span> (pivot1 &lt;= pivot2) &#123;
                k -= (newIndex1 - index1 + <span class="hljs-number">1</span>);
                index1 = newIndex1 + <span class="hljs-number">1</span>;
            &#125; <span class="hljs-keyword">else</span> &#123;
                k -= (newIndex2 - index2 + <span class="hljs-number">1</span>);
                index2 = newIndex2 + <span class="hljs-number">1</span>;
            &#125;
        &#125;
    &#125;
&#125;</code></pre>
<h2 id="141-环形链表"><a href="#141-环形链表" class="headerlink" title="141-环形链表"></a>141-环形链表</h2><p>给定一个链表，判断链表中是否有环。</p>
<p>如果链表中有某个节点，可以通过连续跟踪 next 指针再次到达，则链表中存在环。 为了表示给定链表中的环，我们使用整数 pos 来表示链表尾连接到链表中的位置（索引从 0 开始）。 如果 pos 是 -1，则在该链表中没有环。注意：pos 不作为参数进行传递，仅仅是为了标识链表的实际情况。</p>
<p>如果链表中存在环，则返回 true 。 否则，返回 false 。</p>
<p><code>快慢指针</code> —— 快指针比慢指针每次多走一步，没环不可能相等，有环，环中节点数==快指针比慢指针多走的步数。</p>
<pre><code class="hljs java"><span class="hljs-comment">/**</span>
<span class="hljs-comment"> * Definition for singly-linked list.</span>
<span class="hljs-comment"> * class ListNode &#123;</span>
<span class="hljs-comment"> *     int val;</span>
<span class="hljs-comment"> *     ListNode next;</span>
<span class="hljs-comment"> *     ListNode(int x) &#123;</span>
<span class="hljs-comment"> *         val = x;</span>
<span class="hljs-comment"> *         next = null;</span>
<span class="hljs-comment"> *     &#125;</span>
<span class="hljs-comment"> * &#125;</span>
<span class="hljs-comment"> */</span>
<span class="hljs-keyword">public</span> <span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">Solution</span> </span>&#123;
    <span class="hljs-function"><span class="hljs-keyword">public</span> <span class="hljs-keyword">boolean</span> <span class="hljs-title">hasCycle</span><span class="hljs-params">(ListNode head)</span> </span>&#123;
        ListNode fastPtr = head, slowPtr = head;
        <span class="hljs-keyword">while</span> (fastPtr != <span class="hljs-keyword">null</span> &amp;&amp; fastPtr.next != <span class="hljs-keyword">null</span>)&#123;
            fastPtr = fastPtr.next.next;
            slowPtr = slowPtr.next;
            <span class="hljs-keyword">if</span> (fastPtr == slowPtr) <span class="hljs-keyword">return</span> <span class="hljs-keyword">true</span>;
        &#125;
        <span class="hljs-keyword">return</span> <span class="hljs-keyword">false</span>;
    &#125;
&#125;</code></pre>
<h2 id="142-环形链表Ⅱ"><a href="#142-环形链表Ⅱ" class="headerlink" title="142-环形链表Ⅱ"></a>142-环形链表Ⅱ</h2><p>给定一个链表，返回链表开始入环的第一个节点。 如果链表无环，则返回 null。</p>
<p>为了表示给定链表中的环，我们使用整数 pos 来表示链表尾连接到链表中的位置（索引从 0 开始）。 如果 pos 是 -1，则在该链表中没有环。注意，pos 仅仅是用于标识环的情况，并不会作为参数传递到函数中。</p>
<p>说明：不允许修改给定的链表。</p>
<p><code>HashSet</code></p>
<pre><code class="hljs java"><span class="hljs-comment">/**</span>
<span class="hljs-comment"> * Definition for singly-linked list.</span>
<span class="hljs-comment"> * class ListNode &#123;</span>
<span class="hljs-comment"> *     int val;</span>
<span class="hljs-comment"> *     ListNode next;</span>
<span class="hljs-comment"> *     ListNode(int x) &#123;</span>
<span class="hljs-comment"> *         val = x;</span>
<span class="hljs-comment"> *         next = null;</span>
<span class="hljs-comment"> *     &#125;</span>
<span class="hljs-comment"> * &#125;</span>
<span class="hljs-comment"> */</span>
<span class="hljs-keyword">public</span> <span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">Solution</span> </span>&#123;
    <span class="hljs-function"><span class="hljs-keyword">public</span> ListNode <span class="hljs-title">detectCycle</span><span class="hljs-params">(ListNode head)</span> </span>&#123;
        <span class="hljs-comment">//HashSet</span>
        HashSet&lt;ListNode&gt; set = <span class="hljs-keyword">new</span> HashSet&lt;&gt;();
        <span class="hljs-keyword">while</span> (head != <span class="hljs-keyword">null</span>) &#123;
            <span class="hljs-keyword">if</span> (set.contains(head))&#123;
                <span class="hljs-keyword">return</span> head;
            &#125; <span class="hljs-keyword">else</span> &#123;
                set.add(head);
                head = head.next;
            &#125;
        &#125;
        <span class="hljs-keyword">return</span> <span class="hljs-keyword">null</span>;

    &#125;
&#125;</code></pre>
<p><code>快慢指针</code>，非环节点数为a，环节点数为b，走<code>a+nb</code>步一定在环的入口节点</p>
<ul>
<li>第一次相遇，快指针走的步数为慢指针的两倍，快出来的部分是环的长度的若干倍nb，所以慢指针此时也走了nb步；</li>
</ul>
<pre><code class="hljs java"><span class="hljs-comment">/**</span>
<span class="hljs-comment"> * Definition for singly-linked list.</span>
<span class="hljs-comment"> * class ListNode &#123;</span>
<span class="hljs-comment"> *     int val;</span>
<span class="hljs-comment"> *     ListNode next;</span>
<span class="hljs-comment"> *     ListNode(int x) &#123;</span>
<span class="hljs-comment"> *         val = x;</span>
<span class="hljs-comment"> *         next = null;</span>
<span class="hljs-comment"> *     &#125;</span>
<span class="hljs-comment"> * &#125;</span>
<span class="hljs-comment"> */</span>
<span class="hljs-keyword">public</span> <span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">Solution</span> </span>&#123;
    <span class="hljs-function"><span class="hljs-keyword">public</span> ListNode <span class="hljs-title">detectCycle</span><span class="hljs-params">(ListNode head)</span> </span>&#123;

        <span class="hljs-comment">//快慢指针</span>
        ListNode slowPtr = head, fastPtr = head;
        <span class="hljs-keyword">while</span> (fastPtr != <span class="hljs-keyword">null</span> &amp;&amp; fastPtr.next != <span class="hljs-keyword">null</span>)&#123;
            slowPtr = slowPtr.next;
            fastPtr = fastPtr.next.next;
            <span class="hljs-comment">//第一次相遇，这时候，快指针比慢指针已经多走了链表环的长度</span>
            <span class="hljs-keyword">if</span> (fastPtr == slowPtr) <span class="hljs-keyword">break</span>;
        &#125;
		<span class="hljs-comment">//无环情况</span>
        <span class="hljs-keyword">if</span> (fastPtr == <span class="hljs-keyword">null</span> || fastPtr.next == <span class="hljs-keyword">null</span>)&#123;
            <span class="hljs-keyword">return</span> <span class="hljs-keyword">null</span>;
        &#125;
        <span class="hljs-comment">//慢指针从头开始，快指针模仿慢指针继续每次走一步，两方相遇点即为环的入口节点</span>
        slowPtr = head;
        <span class="hljs-comment">//第二次相遇即环的入口节点</span>
        <span class="hljs-keyword">while</span> (slowPtr != fastPtr)&#123;
            slowPtr = slowPtr.next;
            fastPtr = fastPtr.next;
        &#125;
        <span class="hljs-keyword">return</span> slowPtr;
    &#125;
&#125;</code></pre>
<h2 id="146-LRU缓存机制"><a href="#146-LRU缓存机制" class="headerlink" title="146-LRU缓存机制"></a>146-LRU缓存机制</h2><p>运用你所掌握的数据结构，设计和实现一个  LRU (最近最少使用) 缓存机制 。<br>实现 LRUCache 类：</p>
<ul>
<li>LRUCache(int capacity) 以正整数作为容量 capacity 初始化 LRU 缓存</li>
<li>int get(int key) 如果关键字 key 存在于缓存中，则返回关键字的值，否则返回 -1 。</li>
<li>void put(int key, int value) 如果关键字已经存在，则变更其数据值；如果关键字不存在，则插入该组「关键字-值」。当缓存容量达到上限时，它应该在写入新数据之前删除最久未使用的数据值，从而为新的数据值留出空间。</li>
</ul>
<p>进阶：你是否可以在 O(1) 时间复杂度内完成这两种操作？</p>
<p><code>示例</code></p>
<pre><code class="hljs text">输入
[&quot;LRUCache&quot;, &quot;put&quot;, &quot;put&quot;, &quot;get&quot;, &quot;put&quot;, &quot;get&quot;, &quot;put&quot;, &quot;get&quot;, &quot;get&quot;, &quot;get&quot;]
[[2], [1, 1], [2, 2], [1], [3, 3], [2], [4, 4], [1], [3], [4]]
输出
[null, null, null, 1, null, -1, null, -1, 3, 4]

解释
LRUCache lRUCache = new LRUCache(2);
lRUCache.put(1, 1); // 缓存是 &#123;1=1&#125;
lRUCache.put(2, 2); // 缓存是 &#123;1=1, 2=2&#125;
lRUCache.get(1);    // 返回 1
lRUCache.put(3, 3); // 该操作会使得关键字 2 作废，缓存是 &#123;1=1, 3=3&#125;
lRUCache.get(2);    // 返回 -1 (未找到)
lRUCache.put(4, 4); // 该操作会使得关键字 1 作废，缓存是 &#123;4=4, 3=3&#125;
lRUCache.get(1);    // 返回 -1 (未找到)
lRUCache.get(3);    // 返回 3
lRUCache.get(4);    // 返回 4</code></pre>
<p><code>LinkedHashMap</code></p>
<p>加入插入顺序为key1，key2，key3，key4，那么就会维护一个红线所示的双向链表。</p>
<img src="/2021/05/03/TX%E7%AC%94%E8%AF%95/image-20210320153900676.png" srcset="/img/loading.gif" class="">
<p>get实现：</p>
<ul>
<li>map中不包含当前key，返回-1；</li>
<li>包含当前key，先从LinkedHashMap中删除它，再添加到双向链表的末尾，刷新最久未使用时间（放入双向链表末尾）；</li>
</ul>
<p>put实现：</p>
<ul>
<li>map中包含key，则修改其key值并同时刷新最久未使用时间（放入双向链表末尾）；</li>
<li>map中不包含key，且容量已经满了，则使用迭代器遍历LinkedHashMap中的entry，此时双向链表第一个非头节点的key就是需要淘汰的最久未使用的key，淘汰它，并把新的key放入双向链表末尾；</li>
</ul>
<pre><code class="hljs java"><span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">LRUCache</span> </span>&#123;
    <span class="hljs-keyword">private</span> <span class="hljs-keyword">int</span> capacity = <span class="hljs-number">0</span>;
    <span class="hljs-keyword">private</span> Map&lt;Integer, Integer&gt; map = <span class="hljs-keyword">new</span> LinkedHashMap&lt;&gt;();
    <span class="hljs-function"><span class="hljs-keyword">public</span> <span class="hljs-title">LRUCache</span><span class="hljs-params">(<span class="hljs-keyword">int</span> capacity)</span> </span>&#123;
        <span class="hljs-keyword">this</span>.capacity = capacity;
    &#125;
    
    <span class="hljs-function"><span class="hljs-keyword">public</span> <span class="hljs-keyword">int</span> <span class="hljs-title">get</span><span class="hljs-params">(<span class="hljs-keyword">int</span> key)</span> </span>&#123;
        <span class="hljs-keyword">if</span> (map.containsKey(key))&#123;
            <span class="hljs-keyword">int</span> val = map.get(key);
            <span class="hljs-comment">//先移除再添加，保证每次查询后的key都在双向链表的末尾</span>
            map.remove(key);
            map.put(key, val);
            <span class="hljs-keyword">return</span> val;
        &#125; <span class="hljs-keyword">else</span> &#123;
            <span class="hljs-keyword">return</span> -<span class="hljs-number">1</span>;
        &#125;
    &#125;
    
    <span class="hljs-comment">//put操作也会访问key，所以也要先移除再更新</span>
    <span class="hljs-function"><span class="hljs-keyword">public</span> <span class="hljs-keyword">void</span> <span class="hljs-title">put</span><span class="hljs-params">(<span class="hljs-keyword">int</span> key, <span class="hljs-keyword">int</span> value)</span> </span>&#123;
        <span class="hljs-keyword">if</span> (map.containsKey(key)) &#123;
			map.remove(key);
		&#125; <span class="hljs-keyword">else</span> <span class="hljs-keyword">if</span> (map.size() == capacity) &#123;
            <span class="hljs-comment">//移除链表头节点，即最近最久未使用的节点</span>
			<span class="hljs-keyword">int</span> oldestKey = map.keySet().iterator().next();
            map.remove(oldestKey);
		&#125;
        <span class="hljs-comment">//更新map中键key对应的value</span>
		map.put(key, value);
    &#125;
    
&#125;

<span class="hljs-comment">/**</span>
<span class="hljs-comment"> * Your LRUCache object will be instantiated and called as such:</span>
<span class="hljs-comment"> * LRUCache obj = new LRUCache(capacity);</span>
<span class="hljs-comment"> * int param_1 = obj.get(key);</span>
<span class="hljs-comment"> * obj.put(key,value);</span>
<span class="hljs-comment"> */</span></code></pre>
<h2 id="169-多数元素（求众数）"><a href="#169-多数元素（求众数）" class="headerlink" title="169-多数元素（求众数）"></a>169-多数元素（求众数）</h2><p>给定一个大小为 n 的数组，找到其中的多数元素。多数元素是指在数组中出现次数 大于 ⌊ n/2 ⌋ 的元素。</p>
<p>你可以假设数组是非空的，并且给定的数组总是存在多数元素。</p>
<p><code>投票法</code></p>
<p>从第一个数开始，有自己的一票，如果当前元素和候选元素相同，则候选元素票数+1；如果不同，候选元素票数-1，同时判断票数是否减为0了，是的话就更换候选众数为当前遍历到的数。</p>
<pre><code class="hljs java"><span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">Solution</span> </span>&#123;
    <span class="hljs-function"><span class="hljs-keyword">public</span> <span class="hljs-keyword">int</span> <span class="hljs-title">majorityElement</span><span class="hljs-params">(<span class="hljs-keyword">int</span>[] nums)</span> </span>&#123;
        <span class="hljs-keyword">int</span> candidate = nums[<span class="hljs-number">0</span>];
        <span class="hljs-keyword">int</span> vote = <span class="hljs-number">1</span>;
        <span class="hljs-keyword">for</span> (<span class="hljs-keyword">int</span> i = <span class="hljs-number">1</span>; i &lt; nums.length; i++)&#123;
            <span class="hljs-keyword">if</span> (candidate == nums[i])&#123;
                vote++;
            &#125; <span class="hljs-keyword">else</span> <span class="hljs-keyword">if</span> (--vote == <span class="hljs-number">0</span>)&#123;
                candidate = nums[i];
                vote = <span class="hljs-number">1</span>;
            &#125;
        &#125;
        <span class="hljs-keyword">return</span> candidate;
    &#125;
&#125;</code></pre>
<h2 id="229-求众数"><a href="#229-求众数" class="headerlink" title="229-求众数"></a>229-求众数</h2><p>给定一个大小为 n 的整数数组，找出其中所有出现超过 ⌊ n/3 ⌋ 次的元素。</p>
<p>进阶：尝试设计时间复杂度为 O(n)、空间复杂度为 O(1)的算法解决此问题</p>
<p><code>Map</code></p>
<pre><code class="hljs java"><span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">Solution</span> </span>&#123;
    List&lt;Integer&gt; res = <span class="hljs-keyword">new</span> ArrayList&lt;&gt;();
    Map&lt;Integer, Integer&gt; map = <span class="hljs-keyword">new</span> HashMap&lt;&gt;();
    <span class="hljs-function"><span class="hljs-keyword">public</span> List&lt;Integer&gt; <span class="hljs-title">majorityElement</span><span class="hljs-params">(<span class="hljs-keyword">int</span>[] nums)</span> </span>&#123;
        <span class="hljs-keyword">int</span> n = nums.length;
        <span class="hljs-keyword">for</span> (<span class="hljs-keyword">int</span> num : nums)&#123;
            map.put(num, map.getOrDefault(num, <span class="hljs-number">0</span>) + <span class="hljs-number">1</span>);
        &#125;

        Iterator&lt;Integer&gt; iter = map.keySet().iterator();
        <span class="hljs-keyword">while</span> (iter.hasNext())&#123;
            <span class="hljs-keyword">int</span> key = iter.next();
            <span class="hljs-keyword">if</span> (map.get(key) &gt;= n / <span class="hljs-number">3</span> + <span class="hljs-number">1</span>)&#123;
                res.add(key);
            &#125;
        &#125;
        <span class="hljs-keyword">return</span> res;
    &#125;
&#125;</code></pre>
<p><code>投票法</code>，显然最多有2个出现次数超过 ⌊ n/3 ⌋ 次的元素，所以同时推选两个候选人并配对计数就行</p>
<pre><code class="hljs java"><span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">Solution</span> </span>&#123;
    <span class="hljs-function"><span class="hljs-keyword">public</span> List&lt;Integer&gt; <span class="hljs-title">majorityElement</span><span class="hljs-params">(<span class="hljs-keyword">int</span>[] nums)</span> </span>&#123;
        <span class="hljs-comment">// 创建返回值</span>
        List&lt;Integer&gt; res = <span class="hljs-keyword">new</span> ArrayList&lt;&gt;();
        <span class="hljs-keyword">if</span> (nums == <span class="hljs-keyword">null</span> || nums.length == <span class="hljs-number">0</span>) <span class="hljs-keyword">return</span> res;
        <span class="hljs-comment">// 初始化两个候选人candidate，和他们的计票</span>
        <span class="hljs-keyword">int</span> cand1 = nums[<span class="hljs-number">0</span>], count1 = <span class="hljs-number">0</span>;
        <span class="hljs-keyword">int</span> cand2 = nums[<span class="hljs-number">0</span>], count2 = <span class="hljs-number">0</span>;

        <span class="hljs-comment">// 摩尔投票法，分为两个阶段：配对阶段和计数阶段</span>
        <span class="hljs-comment">// 配对阶段</span>
        <span class="hljs-keyword">for</span> (<span class="hljs-keyword">int</span> num : nums) &#123;
            <span class="hljs-comment">// 投票</span>
            <span class="hljs-keyword">if</span> (cand1 == num) &#123;
                count1++;
                <span class="hljs-keyword">continue</span>;
            &#125;
            <span class="hljs-keyword">if</span> (cand2 == num) &#123;
                count2++;
                <span class="hljs-keyword">continue</span>;
            &#125;

            <span class="hljs-comment">// 第1个候选人配对</span>
            <span class="hljs-keyword">if</span> (count1 == <span class="hljs-number">0</span>) &#123;
                cand1 = num;
                count1++;
                <span class="hljs-keyword">continue</span>;
            &#125;
            <span class="hljs-comment">// 第2个候选人配对</span>
            <span class="hljs-keyword">if</span> (count2 == <span class="hljs-number">0</span>) &#123;
                cand2 = num;
                count2++;
                <span class="hljs-keyword">continue</span>;
            &#125;

            count1--;
            count2--;
        &#125;

        <span class="hljs-comment">// 计数阶段</span>
        <span class="hljs-comment">// 找到了两个候选人之后，需要确定票数是否满足大于 N/3</span>
        count1 = <span class="hljs-number">0</span>;
        count2 = <span class="hljs-number">0</span>;
        <span class="hljs-keyword">for</span> (<span class="hljs-keyword">int</span> num : nums) &#123;
            <span class="hljs-keyword">if</span> (cand1 == num) count1++;
            <span class="hljs-keyword">else</span> <span class="hljs-keyword">if</span> (cand2 == num) count2++;
        &#125;

        <span class="hljs-keyword">if</span> (count1 &gt; nums.length / <span class="hljs-number">3</span>) res.add(cand1);
        <span class="hljs-keyword">if</span> (count2 &gt; nums.length / <span class="hljs-number">3</span>) res.add(cand2);

        <span class="hljs-keyword">return</span> res;
    &#125;
&#125;</code></pre>
<h2 id="234-回文链表"><a href="#234-回文链表" class="headerlink" title="234-回文链表"></a>234-回文链表</h2><p>请判断一个链表是否为回文链表。</p>
<p><code>栈 + 快慢指针</code></p>
<pre><code class="hljs java"><span class="hljs-comment">/**</span>
<span class="hljs-comment"> * Definition for singly-linked list.</span>
<span class="hljs-comment"> * public class ListNode &#123;</span>
<span class="hljs-comment"> *     int val;</span>
<span class="hljs-comment"> *     ListNode next;</span>
<span class="hljs-comment"> *     ListNode() &#123;&#125;</span>
<span class="hljs-comment"> *     ListNode(int val) &#123; this.val = val; &#125;</span>
<span class="hljs-comment"> *     ListNode(int val, ListNode next) &#123; this.val = val; this.next = next; &#125;</span>
<span class="hljs-comment"> * &#125;</span>
<span class="hljs-comment"> */</span>
<span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">Solution</span> </span>&#123;
    <span class="hljs-function"><span class="hljs-keyword">public</span> <span class="hljs-keyword">boolean</span> <span class="hljs-title">isPalindrome</span><span class="hljs-params">(ListNode head)</span> </span>&#123;
        Deque&lt;Integer&gt; stk = <span class="hljs-keyword">new</span> ArrayDeque&lt;&gt;();
        ListNode slowPtr = head;
        ListNode fastPtr = head;
        <span class="hljs-comment">//快指针走到最后一个节点或者空节点时，慢指针正好走到链表的中间节点</span>
        <span class="hljs-keyword">while</span> (fastPtr != <span class="hljs-keyword">null</span> &amp;&amp; fastPtr.next != <span class="hljs-keyword">null</span>)&#123;
            <span class="hljs-comment">//前一半元素压栈</span>
            stk.push(slowPtr.val);
            slowPtr = slowPtr.next;
            fastPtr = fastPtr.next.next;
        &#125;
        <span class="hljs-comment">//奇长链表，此时slowPtr在正中间，且唯一，没被压进栈中</span>
        <span class="hljs-keyword">if</span> (fastPtr != <span class="hljs-keyword">null</span>) &#123;
            stk.push(slowPtr.val);
        &#125;
       <span class="hljs-comment">//依次出栈比较</span>
        <span class="hljs-keyword">while</span> (slowPtr != <span class="hljs-keyword">null</span> &amp;&amp; !stk.isEmpty())&#123;
            <span class="hljs-keyword">int</span> tmp = stk.pop();
            <span class="hljs-keyword">if</span> (slowPtr.val != tmp) <span class="hljs-keyword">return</span> <span class="hljs-keyword">false</span>;
            slowPtr = slowPtr.next;
        &#125;
        <span class="hljs-keyword">return</span> <span class="hljs-keyword">true</span>;

    &#125;
&#125;</code></pre>
<h2 id="102-二叉树的层序遍历"><a href="#102-二叉树的层序遍历" class="headerlink" title="102-二叉树的层序遍历"></a>102-二叉树的层序遍历</h2><p>给你一个二叉树，请你返回其按 <strong>层序遍历</strong> 得到的节点值。 （即逐层地，从左到右访问所有节点）。</p>
<p><code>队列</code></p>
<pre><code class="hljs java"><span class="hljs-comment">/**</span>
<span class="hljs-comment"> * Definition for a binary tree node.</span>
<span class="hljs-comment"> * public class TreeNode &#123;</span>
<span class="hljs-comment"> *     int val;</span>
<span class="hljs-comment"> *     TreeNode left;</span>
<span class="hljs-comment"> *     TreeNode right;</span>
<span class="hljs-comment"> *     TreeNode() &#123;&#125;</span>
<span class="hljs-comment"> *     TreeNode(int val) &#123; this.val = val; &#125;</span>
<span class="hljs-comment"> *     TreeNode(int val, TreeNode left, TreeNode right) &#123;</span>
<span class="hljs-comment"> *         this.val = val;</span>
<span class="hljs-comment"> *         this.left = left;</span>
<span class="hljs-comment"> *         this.right = right;</span>
<span class="hljs-comment"> *     &#125;</span>
<span class="hljs-comment"> * &#125;</span>
<span class="hljs-comment"> */</span>
<span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">Solution</span> </span>&#123;
    <span class="hljs-keyword">public</span> List&lt;List&lt;Integer&gt;&gt; levelOrder(TreeNode root) &#123;
        List&lt;List&lt;Integer&gt;&gt; res = <span class="hljs-keyword">new</span> ArrayList&lt;&gt;();
        <span class="hljs-keyword">if</span> (root == <span class="hljs-keyword">null</span>) <span class="hljs-keyword">return</span> res;
        Deque&lt;TreeNode&gt; q = <span class="hljs-keyword">new</span> ArrayDeque&lt;&gt;();
        q.offer(root);
        <span class="hljs-keyword">while</span> (!q.isEmpty())&#123;
            <span class="hljs-keyword">int</span> size = q.size();
            List&lt;Integer&gt; tmp = <span class="hljs-keyword">new</span> ArrayList&lt;&gt;();
            <span class="hljs-keyword">for</span> (<span class="hljs-keyword">int</span> i = <span class="hljs-number">0</span>; i &lt; size; i++)&#123;
                TreeNode cur = q.poll();
                tmp.add(cur.val);
                <span class="hljs-keyword">if</span> (cur.left != <span class="hljs-keyword">null</span>) q.offer(cur.left);
                <span class="hljs-keyword">if</span> (cur.right != <span class="hljs-keyword">null</span>) q.offer(cur.right);
            &#125;
            res.add(tmp);
        &#125;
        <span class="hljs-keyword">return</span> res;
    &#125;
&#125;</code></pre>
<h2 id="19-删除链表的倒数第N个节点"><a href="#19-删除链表的倒数第N个节点" class="headerlink" title="19-删除链表的倒数第N个节点"></a>19-删除链表的倒数第N个节点</h2><p>给你一个链表，删除链表的倒数第 <code>n</code> 个结点，并且返回链表的头结点。</p>
<p><strong>进阶：</strong>你能尝试使用一趟扫描实现吗？</p>
<img src="/2021/05/03/TX%E7%AC%94%E8%AF%95/image-20210322093937080.png" srcset="/img/loading.gif" class="">
<p><code>前后双指针</code></p>
<pre><code class="hljs java"><span class="hljs-comment">/**</span>
<span class="hljs-comment"> * Definition for singly-linked list.</span>
<span class="hljs-comment"> * public class ListNode &#123;</span>
<span class="hljs-comment"> *     int val;</span>
<span class="hljs-comment"> *     ListNode next;</span>
<span class="hljs-comment"> *     ListNode() &#123;&#125;</span>
<span class="hljs-comment"> *     ListNode(int val) &#123; this.val = val; &#125;</span>
<span class="hljs-comment"> *     ListNode(int val, ListNode next) &#123; this.val = val; this.next = next; &#125;</span>
<span class="hljs-comment"> * &#125;</span>
<span class="hljs-comment"> */</span>
<span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">Solution</span> </span>&#123;
    <span class="hljs-function"><span class="hljs-keyword">public</span> ListNode <span class="hljs-title">removeNthFromEnd</span><span class="hljs-params">(ListNode head, <span class="hljs-keyword">int</span> n)</span> </span>&#123;
        <span class="hljs-comment">//链表长度为1，删除完就返回null</span>
        <span class="hljs-keyword">if</span> (head.next == <span class="hljs-keyword">null</span>) <span class="hljs-keyword">return</span> <span class="hljs-keyword">null</span>;
        ListNode res = <span class="hljs-keyword">new</span> ListNode(<span class="hljs-number">0</span>);
        res.next = head;
        ListNode backPtr = res, frontPtr = res;
        <span class="hljs-comment">//让frontPtr多走n步,等到frontPtr走到末尾，backPtr就走到了要删除的位置的前一个位置</span>
        <span class="hljs-keyword">while</span> (frontPtr.next != <span class="hljs-keyword">null</span>)&#123;
            <span class="hljs-keyword">if</span> (n &gt; <span class="hljs-number">0</span>)&#123;
                frontPtr = frontPtr.next;
                n--;
                <span class="hljs-keyword">continue</span>;
            &#125;
            frontPtr = frontPtr.next;
            backPtr = backPtr.next;
        &#125;
        <span class="hljs-comment">//删除backPtr指向节点的后一个节点</span>
        backPtr.next = backPtr.next.next;
        <span class="hljs-keyword">return</span> res.next;
    &#125;
&#125;</code></pre>
<h2 id="61-旋转链表"><a href="#61-旋转链表" class="headerlink" title="61-旋转链表"></a>61-旋转链表</h2><p>给定一个链表，向右旋转链表，将链表每个节点向右移动 <em>k</em> 个位置，其中 <em>k</em> 是非负数。</p>
<p><code>示例</code></p>
<pre><code class="hljs text">输入: 1-&gt;2-&gt;3-&gt;4-&gt;5-&gt;NULL, k = 2
输出: 4-&gt;5-&gt;1-&gt;2-&gt;3-&gt;NULL
解释:
向右旋转 1 步: 5-&gt;1-&gt;2-&gt;3-&gt;4-&gt;NULL
向右旋转 2 步: 4-&gt;5-&gt;1-&gt;2-&gt;3-&gt;NULL</code></pre>
<p><code>前后指针</code>——前面的指针比后面的指针多走k步</p>
<pre><code class="hljs java"><span class="hljs-comment">/**</span>
<span class="hljs-comment"> * Definition for singly-linked list.</span>
<span class="hljs-comment"> * public class ListNode &#123;</span>
<span class="hljs-comment"> *     int val;</span>
<span class="hljs-comment"> *     ListNode next;</span>
<span class="hljs-comment"> *     ListNode() &#123;&#125;</span>
<span class="hljs-comment"> *     ListNode(int val) &#123; this.val = val; &#125;</span>
<span class="hljs-comment"> *     ListNode(int val, ListNode next) &#123; this.val = val; this.next = next; &#125;</span>
<span class="hljs-comment"> * &#125;</span>
<span class="hljs-comment"> */</span>
<span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">Solution</span> </span>&#123;
    <span class="hljs-function"><span class="hljs-keyword">public</span> ListNode <span class="hljs-title">rotateRight</span><span class="hljs-params">(ListNode head, <span class="hljs-keyword">int</span> k)</span> </span>&#123;
		<span class="hljs-comment">//链表为空 || 链表长为1 || 向右旋转位数为0，返回head即可</span>
        <span class="hljs-keyword">if</span> (head == <span class="hljs-keyword">null</span> || head.next == <span class="hljs-keyword">null</span> || k == <span class="hljs-number">0</span>) <span class="hljs-keyword">return</span> head;
        ListNode backPtr = head, frontPtr = head, q = head;
        <span class="hljs-comment">//得到链表长度</span>
        <span class="hljs-keyword">int</span> cnt = <span class="hljs-number">0</span>;
        <span class="hljs-keyword">while</span> (q != <span class="hljs-keyword">null</span>)&#123;
            cnt++;
            q = q.next;
        &#125;
        <span class="hljs-comment">//旋转次数超过链表长度，取下模即可</span>
        <span class="hljs-keyword">int</span> add = k % cnt;
        <span class="hljs-comment">//取模后为0，相当于不旋转</span>
        <span class="hljs-keyword">if</span> (add == <span class="hljs-number">0</span>) <span class="hljs-keyword">return</span> head;
        
        <span class="hljs-keyword">while</span> (frontPtr.next != <span class="hljs-keyword">null</span>)&#123;
            <span class="hljs-keyword">if</span> (add-- &gt; <span class="hljs-number">0</span>)&#123;
                frontPtr = frontPtr.next;
                <span class="hljs-keyword">continue</span>;
            &#125;
            backPtr = backPtr.next;
            frontPtr = frontPtr.next;
        &#125;
        <span class="hljs-comment">//记录旋转位置</span>
        ListNode rotateHead = backPtr.next;
        <span class="hljs-comment">//链表前面部分的尾部置null</span>
        backPtr.next = <span class="hljs-keyword">null</span>;
        ListNode p = rotateHead;
        <span class="hljs-comment">//遍历到尾部</span>
        <span class="hljs-keyword">while</span> (p.next != <span class="hljs-keyword">null</span>)&#123;
            p = p.next;
        &#125;
        <span class="hljs-comment">//拼接</span>
        p.next = head;
        <span class="hljs-keyword">return</span> rotateHead;
        
    &#125;
&#125;</code></pre>
<p><code>构造环形链表</code></p>
<pre><code class="hljs java"><span class="hljs-comment">/**</span>
<span class="hljs-comment"> * Definition for singly-linked list.</span>
<span class="hljs-comment"> * public class ListNode &#123;</span>
<span class="hljs-comment"> *     int val;</span>
<span class="hljs-comment"> *     ListNode next;</span>
<span class="hljs-comment"> *     ListNode() &#123;&#125;</span>
<span class="hljs-comment"> *     ListNode(int val) &#123; this.val = val; &#125;</span>
<span class="hljs-comment"> *     ListNode(int val, ListNode next) &#123; this.val = val; this.next = next; &#125;</span>
<span class="hljs-comment"> * &#125;</span>
<span class="hljs-comment"> */</span>
<span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">Solution</span> </span>&#123;
    <span class="hljs-function"><span class="hljs-keyword">public</span> ListNode <span class="hljs-title">rotateRight</span><span class="hljs-params">(ListNode head, <span class="hljs-keyword">int</span> k)</span> </span>&#123;

        <span class="hljs-comment">//构造环形链表</span>
        <span class="hljs-keyword">if</span> (head == <span class="hljs-keyword">null</span> || head.next == <span class="hljs-keyword">null</span> || k == <span class="hljs-number">0</span>) <span class="hljs-keyword">return</span> head;
        <span class="hljs-keyword">int</span> cnt = <span class="hljs-number">0</span>;
        ListNode p = head;
        <span class="hljs-keyword">while</span> (p.next != <span class="hljs-keyword">null</span>)&#123;
            cnt++;
            p = p.next;
        &#125;
        <span class="hljs-comment">//注意，这里需要再加1才是链表长度</span>
        cnt++;
        <span class="hljs-comment">//偏移量取模</span>
        k = k % cnt;
        <span class="hljs-comment">//找到尾部成环</span>
        p.next = head;
        <span class="hljs-comment">//再遍历cnt - K个位置拆开环即可</span>
        <span class="hljs-keyword">int</span> offset = cnt - k;
        <span class="hljs-keyword">while</span> (offset-- &gt; <span class="hljs-number">0</span>)&#123;
            head = head.next;
            p = p.next;
        &#125;
        p.next = <span class="hljs-keyword">null</span>;
        <span class="hljs-keyword">return</span> head;
    &#125;
&#125;</code></pre>
<h2 id="153-寻找旋转排序数组中的最小值"><a href="#153-寻找旋转排序数组中的最小值" class="headerlink" title="153-寻找旋转排序数组中的最小值"></a>153-寻找旋转排序数组中的最小值</h2><p>假设按照升序排序的数组在预先未知的某个点上进行了旋转。例如，数组 [0,1,2,4,5,6,7] 可能变为 [4,5,6,7,0,1,2] 。</p>
<p>请找出其中最小的元素。</p>
<p><code>二分搜素</code></p>
<img src="/2021/05/03/TX%E7%AC%94%E8%AF%95/image-20210322140518129.png" srcset="/img/loading.gif" class="">
<pre><code class="hljs java"><span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">Solution</span> </span>&#123;
    <span class="hljs-function"><span class="hljs-keyword">public</span> <span class="hljs-keyword">int</span> <span class="hljs-title">findMin</span><span class="hljs-params">(<span class="hljs-keyword">int</span>[] nums)</span> </span>&#123;
        <span class="hljs-keyword">int</span> left = <span class="hljs-number">0</span>, right = nums.length - <span class="hljs-number">1</span>;
        <span class="hljs-comment">//注意left &lt; right - 1</span>
        <span class="hljs-keyword">while</span> (left &lt; right - <span class="hljs-number">1</span>)&#123;
            <span class="hljs-keyword">int</span> mid = (right - left) / <span class="hljs-number">2</span> + left;
            <span class="hljs-keyword">if</span> (nums[left] &lt; nums[mid])&#123;
                left = mid;
            &#125; <span class="hljs-keyword">else</span> &#123;
                right = mid;
            &#125;
            <span class="hljs-keyword">return</span> nums[right];
        &#125;
    &#125;
&#125;</code></pre>
<h2 id="215-数组中的第K个最大元素"><a href="#215-数组中的第K个最大元素" class="headerlink" title="215-数组中的第K个最大元素"></a>215-数组中的第K个最大元素</h2><p>在未排序的数组中找到第 <strong>k</strong> 个最大的元素。请注意，你需要找的是数组排序后的第 k 个最大的元素，而不是第 k 个不同的元素。</p>
<p><code>优先权队列</code>——最大堆/最小堆</p>
<pre><code class="hljs java"><span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">Solution</span> </span>&#123;
    <span class="hljs-keyword">int</span> res = <span class="hljs-number">0</span>;
    <span class="hljs-function"><span class="hljs-keyword">public</span> <span class="hljs-keyword">int</span> <span class="hljs-title">findKthLargest</span><span class="hljs-params">(<span class="hljs-keyword">int</span>[] nums, <span class="hljs-keyword">int</span> k)</span> </span>&#123;
        <span class="hljs-keyword">int</span> n = nums.length;
        <span class="hljs-keyword">if</span> (k &gt; n / <span class="hljs-number">2</span>)&#123;
            PriorityQueue&lt;Integer&gt; maxHeap = <span class="hljs-keyword">new</span> PriorityQueue&lt;&gt;(n, (a, b) -&gt; b - a);
            getRes(maxHeap, nums, k);

        &#125; <span class="hljs-keyword">else</span> &#123;
            PriorityQueue&lt;Integer&gt; minHeap = <span class="hljs-keyword">new</span> PriorityQueue&lt;&gt;(n);
            getRes(minHeap, nums, n - k + <span class="hljs-number">1</span>);
        &#125;
        <span class="hljs-keyword">return</span> res;
    &#125;

    <span class="hljs-comment">//从最大堆或者最小堆中获取结果</span>
    <span class="hljs-function"><span class="hljs-keyword">public</span> <span class="hljs-keyword">void</span> <span class="hljs-title">getRes</span><span class="hljs-params">(PriorityQueue&lt;Integer&gt; heap, <span class="hljs-keyword">int</span>[] nums, <span class="hljs-keyword">int</span> cnt)</span></span>&#123;
        <span class="hljs-keyword">for</span> (<span class="hljs-keyword">int</span> num : nums)&#123;
            heap.offer(num);
        &#125;
        <span class="hljs-keyword">while</span> (cnt-- &gt; <span class="hljs-number">0</span>)&#123;
            res = heap.poll();
        &#125;
    &#125;
&#125;</code></pre>
<h2 id="155-最小栈"><a href="#155-最小栈" class="headerlink" title="155-最小栈"></a>155-最小栈</h2><p>设计一个支持 push ，pop ，top 操作，并能在常数时间内检索到最小元素的栈。</p>
<ul>
<li>push(x) —— 将元素 x 推入栈中。</li>
<li>pop() —— 删除栈顶的元素。</li>
<li>top() —— 获取栈顶元素。</li>
<li>getMin() —— 检索栈中的最小元素。</li>
</ul>
<pre><code class="hljs java"><span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">MinStack</span> </span>&#123;
    Deque&lt;Integer&gt; stk1;
    Deque&lt;Integer&gt; stk2;
    <span class="hljs-comment">/** initialize your data structure here. */</span>
    <span class="hljs-function"><span class="hljs-keyword">public</span> <span class="hljs-title">MinStack</span><span class="hljs-params">()</span> </span>&#123;
        stk1 = <span class="hljs-keyword">new</span> ArrayDeque&lt;&gt;();
        stk2 = <span class="hljs-keyword">new</span> ArrayDeque&lt;&gt;();
        <span class="hljs-comment">//当前栈中无元素，所以设置辅助栈最小元素为Integer.MAX_VALUE，使之不会为空</span>
        stk2.push(Integer.MAX_VALUE);
    &#125;
    
    <span class="hljs-function"><span class="hljs-keyword">public</span> <span class="hljs-keyword">void</span> <span class="hljs-title">push</span><span class="hljs-params">(<span class="hljs-keyword">int</span> val)</span> </span>&#123;
        stk1.push(val);
        stk2.push(Math.min(val, stk2.peek()));
    &#125;
    
    <span class="hljs-function"><span class="hljs-keyword">public</span> <span class="hljs-keyword">void</span> <span class="hljs-title">pop</span><span class="hljs-params">()</span> </span>&#123;
        <span class="hljs-keyword">if</span> (!stk1.isEmpty())&#123;
            stk1.pop();
            stk2.pop();
        &#125; <span class="hljs-keyword">else</span> &#123;
            <span class="hljs-keyword">return</span>;
        &#125;
    &#125;
    
    <span class="hljs-function"><span class="hljs-keyword">public</span> <span class="hljs-keyword">int</span> <span class="hljs-title">top</span><span class="hljs-params">()</span> </span>&#123;
        <span class="hljs-keyword">return</span> stk1.peek();
    &#125;
    
    <span class="hljs-function"><span class="hljs-keyword">public</span> <span class="hljs-keyword">int</span> <span class="hljs-title">getMin</span><span class="hljs-params">()</span> </span>&#123;
        <span class="hljs-keyword">return</span> stk2.peek();
    &#125;
&#125;

<span class="hljs-comment">/**</span>
<span class="hljs-comment"> * Your MinStack object will be instantiated and called as such:</span>
<span class="hljs-comment"> * MinStack obj = new MinStack();</span>
<span class="hljs-comment"> * obj.push(val);</span>
<span class="hljs-comment"> * obj.pop();</span>
<span class="hljs-comment"> * int param_3 = obj.top();</span>
<span class="hljs-comment"> * int param_4 = obj.getMin();</span>
<span class="hljs-comment"> */</span></code></pre>
<h2 id="240-搜索二维矩阵"><a href="#240-搜索二维矩阵" class="headerlink" title="240-搜索二维矩阵"></a>240-搜索二维矩阵</h2><p>编写一个高效的算法来搜索 m x n 矩阵 matrix 中的一个目标值 target 。该矩阵具有以下特性：</p>
<ul>
<li>每行的元素从左到右升序排列</li>
<li>每列的元素从上到下升序排列</li>
</ul>
<img src="/2021/05/03/TX%E7%AC%94%E8%AF%95/image-20210322144900866.png" srcset="/img/loading.gif" class="">
<p><code>双指针</code> —— 从右上角开始找</p>
<pre><code class="hljs java"><span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">Solution</span> </span>&#123;
    <span class="hljs-function"><span class="hljs-keyword">public</span> <span class="hljs-keyword">boolean</span> <span class="hljs-title">searchMatrix</span><span class="hljs-params">(<span class="hljs-keyword">int</span>[][] matrix, <span class="hljs-keyword">int</span> target)</span> </span>&#123;
        <span class="hljs-keyword">int</span> m = matrix.length, n = matrix[<span class="hljs-number">0</span>].length;
        <span class="hljs-keyword">int</span> row = <span class="hljs-number">0</span>, col = n - <span class="hljs-number">1</span>;
        <span class="hljs-keyword">while</span> (row &lt;= m - <span class="hljs-number">1</span> &amp;&amp; col &gt;= <span class="hljs-number">0</span>)&#123;
            <span class="hljs-keyword">if</span> (matrix[row][col] &gt; target)&#123;
                col--;
            &#125; <span class="hljs-keyword">else</span> <span class="hljs-keyword">if</span> (matrix[row][col] &lt; target)&#123;
                row++;
            &#125; <span class="hljs-keyword">else</span> &#123;
                <span class="hljs-keyword">return</span> <span class="hljs-keyword">true</span>;
            &#125;
        &#125;
        <span class="hljs-keyword">return</span> <span class="hljs-keyword">false</span>;
    &#125;
&#125;</code></pre>
<h2 id="21-合并两个有序链表"><a href="#21-合并两个有序链表" class="headerlink" title="21-合并两个有序链表"></a>21-合并两个有序链表</h2><p>将两个升序链表合并为一个新的 <strong>升序</strong> 链表并返回。新链表是通过拼接给定的两个链表的所有节点组成的。 </p>
<img src="/2021/05/03/TX%E7%AC%94%E8%AF%95/image-20210322145657980.png" srcset="/img/loading.gif" class="">
<pre><code class="hljs java"><span class="hljs-comment">/**</span>
<span class="hljs-comment"> * Definition for singly-linked list.</span>
<span class="hljs-comment"> * public class ListNode &#123;</span>
<span class="hljs-comment"> *     int val;</span>
<span class="hljs-comment"> *     ListNode next;</span>
<span class="hljs-comment"> *     ListNode() &#123;&#125;</span>
<span class="hljs-comment"> *     ListNode(int val) &#123; this.val = val; &#125;</span>
<span class="hljs-comment"> *     ListNode(int val, ListNode next) &#123; this.val = val; this.next = next; &#125;</span>
<span class="hljs-comment"> * &#125;</span>
<span class="hljs-comment"> */</span>
<span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">Solution</span> </span>&#123;
    <span class="hljs-function"><span class="hljs-keyword">public</span> ListNode <span class="hljs-title">mergeTwoLists</span><span class="hljs-params">(ListNode l1, ListNode l2)</span> </span>&#123;
        ListNode res = <span class="hljs-keyword">new</span> ListNode(<span class="hljs-number">0</span>);
        ListNode p = res;
        <span class="hljs-keyword">while</span> (l1 != <span class="hljs-keyword">null</span> &amp;&amp; l2 != <span class="hljs-keyword">null</span>)&#123;
            <span class="hljs-keyword">if</span> (l1.val &lt;= l2.val)&#123;
                p.next = <span class="hljs-keyword">new</span> ListNode(l1.val);
                l1 = l1.next;
            &#125; <span class="hljs-keyword">else</span> &#123;
                p.next = <span class="hljs-keyword">new</span> ListNode(l2.val);
                l2 = l2.next;
            &#125;
            p = p.next;
        &#125;
        p.next = l1 != <span class="hljs-keyword">null</span> ? l1 : l2;
        <span class="hljs-keyword">return</span> res.next;
    &#125;
&#125;</code></pre>
<h2 id="53-最大子序和"><a href="#53-最大子序和" class="headerlink" title="53-最大子序和"></a>53-最大子序和</h2><p>给定一个整数数组 <code>nums</code> ，找到一个具有最大和的连续子数组（子数组最少包含一个元素），返回其最大和。</p>
<p><code>动态规划</code></p>
<pre><code class="hljs java"><span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">Solution</span> </span>&#123;
    <span class="hljs-function"><span class="hljs-keyword">public</span> <span class="hljs-keyword">int</span> <span class="hljs-title">maxSubArray</span><span class="hljs-params">(<span class="hljs-keyword">int</span>[] nums)</span> </span>&#123;
        <span class="hljs-keyword">int</span> n = nums.length;
        <span class="hljs-keyword">if</span> (n == <span class="hljs-number">1</span>) <span class="hljs-keyword">return</span> nums[<span class="hljs-number">0</span>]; 
        <span class="hljs-keyword">int</span> sum = nums[<span class="hljs-number">0</span>];

        <span class="hljs-keyword">int</span> dp_0 = nums[<span class="hljs-number">0</span>], dp_1 = <span class="hljs-number">0</span>;
        <span class="hljs-keyword">for</span> (<span class="hljs-keyword">int</span> i = <span class="hljs-number">1</span>; i &lt; n; i++)&#123;
            dp_1 = Math.max(dp_0 + nums[i], nums[i]);
            <span class="hljs-comment">//在所有以nums[i]结尾的子数组最大和中取最大的</span>
            sum = Math.max(sum, dp_1);
            dp_0 = dp_1;
        &#125;
        <span class="hljs-keyword">return</span> sum;
    &#125;
&#125;</code></pre>
<h2 id="160-相交链表"><a href="#160-相交链表" class="headerlink" title="160-相交链表"></a>160-相交链表</h2><p>编写一个程序，找到两个单链表相交的起始节点。</p>
<p>如下面的两个链表<strong>：</strong></p>
<img src="/2021/05/03/TX%E7%AC%94%E8%AF%95/160_statement.png" srcset="/img/loading.gif" class="">
<p>在节点 c1 开始相交。</p>
<p><code>双指针</code></p>
<pre><code class="hljs java"><span class="hljs-comment">/**</span>
<span class="hljs-comment"> * Definition for singly-linked list.</span>
<span class="hljs-comment"> * public class ListNode &#123;</span>
<span class="hljs-comment"> *     int val;</span>
<span class="hljs-comment"> *     ListNode next;</span>
<span class="hljs-comment"> *     ListNode(int x) &#123;</span>
<span class="hljs-comment"> *         val = x;</span>
<span class="hljs-comment"> *         next = null;</span>
<span class="hljs-comment"> *     &#125;</span>
<span class="hljs-comment"> * &#125;</span>
<span class="hljs-comment"> */</span>
<span class="hljs-keyword">public</span> <span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">Solution</span> </span>&#123;
    <span class="hljs-function"><span class="hljs-keyword">public</span> ListNode <span class="hljs-title">getIntersectionNode</span><span class="hljs-params">(ListNode headA, ListNode headB)</span> </span>&#123;
        ListNode p = headA, q = headB;
        <span class="hljs-keyword">while</span> (p != q)&#123;
            p = p == <span class="hljs-keyword">null</span> ? headB : p.next;
            q = q == <span class="hljs-keyword">null</span> ? headA : q.next;
        &#125;
        <span class="hljs-keyword">return</span> p;
    &#125;
&#125;</code></pre>
<h2 id="232-用栈实现队列"><a href="#232-用栈实现队列" class="headerlink" title="232-用栈实现队列"></a>232-用栈实现队列</h2><img src="/2021/05/03/TX%E7%AC%94%E8%AF%95/image-20210322164318139.png" srcset="/img/loading.gif" class="">
<pre><code class="hljs java"><span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">MyQueue</span> </span>&#123;

    Deque&lt;Integer&gt; stk1;
    Deque&lt;Integer&gt; stk2;

    <span class="hljs-comment">/** Initialize your data structure here. */</span>
    <span class="hljs-function"><span class="hljs-keyword">public</span> <span class="hljs-title">MyQueue</span><span class="hljs-params">()</span> </span>&#123;
        stk1 = <span class="hljs-keyword">new</span> ArrayDeque&lt;&gt;();
        stk2 = <span class="hljs-keyword">new</span> ArrayDeque&lt;&gt;();
    &#125;
    
    <span class="hljs-comment">/** Push element x to the back of queue. */</span>
    <span class="hljs-function"><span class="hljs-keyword">public</span> <span class="hljs-keyword">void</span> <span class="hljs-title">push</span><span class="hljs-params">(<span class="hljs-keyword">int</span> x)</span> </span>&#123;
        stk1.push(x);
    &#125;
    
    <span class="hljs-comment">/** Removes the element from in front of queue and returns that element. */</span>
    <span class="hljs-function"><span class="hljs-keyword">public</span> <span class="hljs-keyword">int</span> <span class="hljs-title">pop</span><span class="hljs-params">()</span> </span>&#123;
        <span class="hljs-keyword">if</span> (stk2.isEmpty())&#123;
            <span class="hljs-keyword">while</span> (!stk1.isEmpty())&#123;
                stk2.push(stk1.pop());
            &#125;
        &#125;
        <span class="hljs-keyword">return</span> stk2.pop();
    &#125;
    
    <span class="hljs-comment">/** Get the front element. */</span>
    <span class="hljs-function"><span class="hljs-keyword">public</span> <span class="hljs-keyword">int</span> <span class="hljs-title">peek</span><span class="hljs-params">()</span> </span>&#123;
        <span class="hljs-keyword">if</span> (stk2.isEmpty())&#123;
            <span class="hljs-keyword">while</span> (!stk1.isEmpty())&#123;
                stk2.push(stk1.pop());
            &#125;
            
        &#125;
        <span class="hljs-keyword">return</span> stk2.peek();
    &#125;
    
    <span class="hljs-comment">/** Returns whether the queue is empty. */</span>
    <span class="hljs-function"><span class="hljs-keyword">public</span> <span class="hljs-keyword">boolean</span> <span class="hljs-title">empty</span><span class="hljs-params">()</span> </span>&#123;
        <span class="hljs-comment">//两个栈都必须为空，队列才为空</span>
        <span class="hljs-keyword">return</span> stk2.isEmpty() &amp;&amp; stk1.isEmpty();
    &#125;
&#125;

<span class="hljs-comment">/**</span>
<span class="hljs-comment"> * Your MyQueue object will be instantiated and called as such:</span>
<span class="hljs-comment"> * MyQueue obj = new MyQueue();</span>
<span class="hljs-comment"> * obj.push(x);</span>
<span class="hljs-comment"> * int param_2 = obj.pop();</span>
<span class="hljs-comment"> * int param_3 = obj.peek();</span>
<span class="hljs-comment"> * boolean param_4 = obj.empty();</span>
<span class="hljs-comment"> */</span></code></pre>
<h2 id="20-有效的括号"><a href="#20-有效的括号" class="headerlink" title="20-有效的括号"></a>20-有效的括号</h2><p>给定一个只包括 ‘(‘，’)’，’{‘，’}’，’[‘，’]’ 的字符串 s ，判断字符串是否有效。</p>
<p>有效字符串需满足：</p>
<ul>
<li>左括号必须用相同类型的右括号闭合。</li>
<li>左括号必须以正确的顺序闭合。</li>
</ul>
<pre><code class="hljs java"><span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">Solution</span> </span>&#123;
    <span class="hljs-function"><span class="hljs-keyword">public</span> <span class="hljs-keyword">boolean</span> <span class="hljs-title">isValid</span><span class="hljs-params">(String s)</span> </span>&#123;
        <span class="hljs-comment">//top从1开始</span>
        <span class="hljs-keyword">int</span> top = <span class="hljs-number">1</span>;
        <span class="hljs-keyword">char</span>[] stack = <span class="hljs-keyword">new</span> <span class="hljs-keyword">char</span>[s.length() + <span class="hljs-number">1</span>];
        <span class="hljs-comment">//遍历字符串中每个字符的简便写法</span>
        <span class="hljs-keyword">for</span>(<span class="hljs-keyword">char</span> c: s.toCharArray())&#123;
            <span class="hljs-keyword">if</span>(c == <span class="hljs-string">&#x27;(&#x27;</span> || c == <span class="hljs-string">&#x27;[&#x27;</span> || c == <span class="hljs-string">&#x27;&#123;&#x27;</span>)&#123;
                <span class="hljs-comment">//遇左括号入栈</span>
                stack[top++] = c;
            &#125;<span class="hljs-keyword">else</span> <span class="hljs-keyword">if</span>(c == <span class="hljs-string">&#x27;)&#x27;</span> &amp;&amp; stack[--top] != <span class="hljs-string">&#x27;(&#x27;</span>)&#123;<span class="hljs-comment">//遇右括号则判断是否与此时栈顶元素匹配</span>
                <span class="hljs-keyword">return</span> <span class="hljs-keyword">false</span>;   <span class="hljs-comment">//不匹配则直接返回false</span>
            &#125;<span class="hljs-keyword">else</span> <span class="hljs-keyword">if</span>(c == <span class="hljs-string">&#x27;]&#x27;</span> &amp;&amp; stack[--top] != <span class="hljs-string">&#x27;[&#x27;</span>)&#123;
                <span class="hljs-keyword">return</span> <span class="hljs-keyword">false</span>;
            &#125;<span class="hljs-keyword">else</span> <span class="hljs-keyword">if</span>(c == <span class="hljs-string">&#x27;&#125;&#x27;</span> &amp;&amp; stack[--top] != <span class="hljs-string">&#x27;&#123;&#x27;</span>)&#123;
                <span class="hljs-keyword">return</span> <span class="hljs-keyword">false</span>;
            &#125;
        &#125;
        <span class="hljs-keyword">return</span> top == <span class="hljs-number">1</span>; <span class="hljs-comment">//判断空栈条件是否成立，若&quot;top==1为真&quot;说,明此时栈中元素全部成功匹配</span>
    &#125;
&#125;</code></pre>
<h2 id="136-只出现一次的数字"><a href="#136-只出现一次的数字" class="headerlink" title="136-只出现一次的数字"></a>136-只出现一次的数字</h2><p>给定一个非空整数数组，除了某个元素只出现一次以外，其余每个元素均出现两次。找出那个只出现了一次的元素。</p>
<p>说明：</p>
<p>你的算法应该具有线性时间复杂度。 你可以不使用额外空间来实现吗？</p>
<p><code>位运算</code>—— 异或</p>
<pre><code class="hljs java"><span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">Solution</span> </span>&#123;
    <span class="hljs-function"><span class="hljs-keyword">public</span> <span class="hljs-keyword">int</span> <span class="hljs-title">singleNumber</span><span class="hljs-params">(<span class="hljs-keyword">int</span>[] nums)</span> </span>&#123;
        <span class="hljs-keyword">int</span> sum = <span class="hljs-number">0</span>;
        <span class="hljs-keyword">for</span> (<span class="hljs-keyword">int</span> num : nums)&#123;
            sum ^= num;
        &#125;
        <span class="hljs-keyword">return</span> sum;
    &#125;
&#125;</code></pre>
<h2 id="23-合并K个排序链表"><a href="#23-合并K个排序链表" class="headerlink" title="23-合并K个排序链表"></a>23-合并K个排序链表</h2><p>给你一个链表数组，每个链表都已经按升序排列。</p>
<p>请你将所有链表合并到一个升序链表中，返回合并后的链表。</p>
<pre><code class="hljs java"><span class="hljs-comment">/**</span>
<span class="hljs-comment"> * Definition for singly-linked list.</span>
<span class="hljs-comment"> * public class ListNode &#123;</span>
<span class="hljs-comment"> *     int val;</span>
<span class="hljs-comment"> *     ListNode next;</span>
<span class="hljs-comment"> *     ListNode() &#123;&#125;</span>
<span class="hljs-comment"> *     ListNode(int val) &#123; this.val = val; &#125;</span>
<span class="hljs-comment"> *     ListNode(int val, ListNode next) &#123; this.val = val; this.next = next; &#125;</span>
<span class="hljs-comment"> * &#125;</span>
<span class="hljs-comment"> */</span>
<span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">Solution</span> </span>&#123;
    <span class="hljs-function"><span class="hljs-keyword">public</span> ListNode <span class="hljs-title">mergeKLists</span><span class="hljs-params">(ListNode[] lists)</span> </span>&#123;
        <span class="hljs-keyword">int</span> n = lists.length;
        ListNode res = <span class="hljs-keyword">null</span>;
        <span class="hljs-keyword">for</span> (<span class="hljs-keyword">int</span> i = <span class="hljs-number">0</span>; i &lt; n; i++)&#123;
            <span class="hljs-comment">//两个两个合并</span>
            res = mergeTwoLists(res, lists[i]);
        &#125;
        <span class="hljs-keyword">return</span> res;
    &#125;
	
    <span class="hljs-function"><span class="hljs-keyword">public</span> ListNode <span class="hljs-title">mergeTwoLists</span><span class="hljs-params">(ListNode l1, ListNode l2)</span></span>&#123;
        ListNode res = <span class="hljs-keyword">new</span> ListNode(<span class="hljs-number">0</span>);
        ListNode pre = res;
        <span class="hljs-keyword">while</span> (l1 != <span class="hljs-keyword">null</span> &amp;&amp; l2 != <span class="hljs-keyword">null</span>)&#123;
            <span class="hljs-keyword">if</span> (l1.val &lt;= l2.val)&#123;
                pre.next = l1;
                l1 = l1.next;
            &#125; <span class="hljs-keyword">else</span> &#123;
                pre.next = l2;
                l2 = l2.next;
            &#125;
            pre = pre.next;
        &#125;
        pre.next = l1 != <span class="hljs-keyword">null</span> ? l1 : l2;
        <span class="hljs-keyword">return</span> res.next;
    &#125;
&#125;</code></pre>
<h2 id="236-二叉树的最近公共祖先"><a href="#236-二叉树的最近公共祖先" class="headerlink" title="236-二叉树的最近公共祖先"></a>236-二叉树的最近公共祖先</h2><p>给定一个二叉树, 找到该树中两个指定节点的最近公共祖先。<strong>一个节点也可以是它自己的祖先</strong></p>
<pre><code class="hljs java"><span class="hljs-comment">/**</span>
<span class="hljs-comment"> * Definition for a binary tree node.</span>
<span class="hljs-comment"> * public class TreeNode &#123;</span>
<span class="hljs-comment"> *     int val;</span>
<span class="hljs-comment"> *     TreeNode left;</span>
<span class="hljs-comment"> *     TreeNode right;</span>
<span class="hljs-comment"> *     TreeNode(int x) &#123; val = x; &#125;</span>
<span class="hljs-comment"> * &#125;</span>
<span class="hljs-comment"> */</span>
<span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">Solution</span> </span>&#123;
    <span class="hljs-function"><span class="hljs-keyword">public</span> TreeNode <span class="hljs-title">lowestCommonAncestor</span><span class="hljs-params">(TreeNode root, TreeNode p, TreeNode q)</span> </span>&#123;
        <span class="hljs-comment">//root为空，返回null;</span>
        <span class="hljs-comment">//p或q为当前子树的根，则LCA为p或q</span>
        <span class="hljs-keyword">if</span> (root == <span class="hljs-keyword">null</span> || p == root || q == root) <span class="hljs-keyword">return</span> root;
        
        TreeNode left = lowestCommonAncestor(root.left, p, q);
        TreeNode right = lowestCommonAncestor(root.right, p, q);
        
        <span class="hljs-comment">//p,q分别在左右子树，左右子树的根就是LCA</span>
        <span class="hljs-keyword">if</span> (left != <span class="hljs-keyword">null</span> &amp;&amp; right != <span class="hljs-keyword">null</span>)&#123;
            <span class="hljs-keyword">return</span> root;
        &#125;
        <span class="hljs-comment">//p,q在同一子树，要么p为LCA，要么q为LCA</span>
        <span class="hljs-keyword">return</span> left == <span class="hljs-keyword">null</span> ? right : left;
    &#125;
&#125;</code></pre>
<h2 id="144-二叉树的前序遍历"><a href="#144-二叉树的前序遍历" class="headerlink" title="144-二叉树的前序遍历"></a>144-二叉树的前序遍历</h2><pre><code class="hljs java"><span class="hljs-comment">/**</span>
<span class="hljs-comment"> * Definition for a binary tree node.</span>
<span class="hljs-comment"> * public class TreeNode &#123;</span>
<span class="hljs-comment"> *     int val;</span>
<span class="hljs-comment"> *     TreeNode left;</span>
<span class="hljs-comment"> *     TreeNode right;</span>
<span class="hljs-comment"> *     TreeNode() &#123;&#125;</span>
<span class="hljs-comment"> *     TreeNode(int val) &#123; this.val = val; &#125;</span>
<span class="hljs-comment"> *     TreeNode(int val, TreeNode left, TreeNode right) &#123;</span>
<span class="hljs-comment"> *         this.val = val;</span>
<span class="hljs-comment"> *         this.left = left;</span>
<span class="hljs-comment"> *         this.right = right;</span>
<span class="hljs-comment"> *     &#125;</span>
<span class="hljs-comment"> * &#125;</span>
<span class="hljs-comment"> */</span>
<span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">Solution</span> </span>&#123;
    List&lt;Integer&gt; res = <span class="hljs-keyword">new</span> ArrayList&lt;&gt;();
    <span class="hljs-function"><span class="hljs-keyword">public</span> List&lt;Integer&gt; <span class="hljs-title">preorderTraversal</span><span class="hljs-params">(TreeNode root)</span> </span>&#123;
        preOrder(root);
        <span class="hljs-keyword">return</span> res;
    &#125;

    <span class="hljs-function"><span class="hljs-keyword">public</span> <span class="hljs-keyword">void</span> <span class="hljs-title">preOrder</span><span class="hljs-params">(TreeNode node)</span></span>&#123;
        <span class="hljs-keyword">if</span> (node == <span class="hljs-keyword">null</span>) <span class="hljs-keyword">return</span>;
        res.add(node.val);
        preOrder(node.left);
        preOrder(node.right);
    &#125;
&#125;</code></pre>
<h2 id="172-阶乘后的0"><a href="#172-阶乘后的0" class="headerlink" title="172-阶乘后的0"></a>172-阶乘后的0</h2><p>给定一个整数 <em>n</em>，返回 <em>n</em>! 结果尾数中零的数量</p>
<p><code>数学</code></p>
<ul>
<li>每个5可以提供一个0</li>
<li>每个25可以提供两个0</li>
<li>每个125可以提供3个0</li>
<li>。。。</li>
</ul>
<pre><code class="hljs java"><span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">Solution</span> </span>&#123;
    <span class="hljs-function"><span class="hljs-keyword">public</span> <span class="hljs-keyword">int</span> <span class="hljs-title">trailingZeroes</span><span class="hljs-params">(<span class="hljs-keyword">int</span> n)</span> </span>&#123;
        <span class="hljs-keyword">int</span> cnt = <span class="hljs-number">0</span>;
        <span class="hljs-keyword">int</span> base = <span class="hljs-number">1</span>;
        <span class="hljs-comment">//等价于求1~n中，质因子5出现的次数</span>
        <span class="hljs-keyword">while</span> (base &lt; n)&#123;
            base = base * <span class="hljs-number">5</span>;
            cnt += n / base;
        &#125;
        <span class="hljs-keyword">return</span> cnt;
        
    &#125;
&#125;</code></pre>
<h2 id="110-平衡二叉树"><a href="#110-平衡二叉树" class="headerlink" title="110-平衡二叉树"></a>110-平衡二叉树</h2><pre><code class="hljs java"><span class="hljs-comment">/**</span>
<span class="hljs-comment"> * Definition for a binary tree node.</span>
<span class="hljs-comment"> * public class TreeNode &#123;</span>
<span class="hljs-comment"> *     int val;</span>
<span class="hljs-comment"> *     TreeNode left;</span>
<span class="hljs-comment"> *     TreeNode right;</span>
<span class="hljs-comment"> *     TreeNode() &#123;&#125;</span>
<span class="hljs-comment"> *     TreeNode(int val) &#123; this.val = val; &#125;</span>
<span class="hljs-comment"> *     TreeNode(int val, TreeNode left, TreeNode right) &#123;</span>
<span class="hljs-comment"> *         this.val = val;</span>
<span class="hljs-comment"> *         this.left = left;</span>
<span class="hljs-comment"> *         this.right = right;</span>
<span class="hljs-comment"> *     &#125;</span>
<span class="hljs-comment"> * &#125;</span>
<span class="hljs-comment"> */</span>
<span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">Solution</span> </span>&#123;
    <span class="hljs-function"><span class="hljs-keyword">public</span> <span class="hljs-keyword">boolean</span> <span class="hljs-title">isBalanced</span><span class="hljs-params">(TreeNode root)</span> </span>&#123;
        <span class="hljs-keyword">if</span> (root == <span class="hljs-keyword">null</span>) <span class="hljs-keyword">return</span> <span class="hljs-keyword">true</span>;
        <span class="hljs-keyword">if</span> (Math.abs(getHeight(root.left) - getHeight(root.right)) &gt; <span class="hljs-number">1</span>)&#123;
            <span class="hljs-keyword">return</span> <span class="hljs-keyword">false</span>;
        &#125;
        <span class="hljs-keyword">return</span> isBalanced(root.left) &amp;&amp; isBalanced(root.right);
    &#125;
    
    <span class="hljs-function"><span class="hljs-keyword">public</span> <span class="hljs-keyword">int</span> <span class="hljs-title">getHeight</span><span class="hljs-params">(TreeNode node)</span></span>&#123;
        <span class="hljs-keyword">if</span> (node == <span class="hljs-keyword">null</span>) <span class="hljs-keyword">return</span> <span class="hljs-number">0</span>;
        <span class="hljs-keyword">return</span> <span class="hljs-number">1</span> + Math.max(getHeight(node.left), getHeight(node.right));
    &#125;
&#125;</code></pre>
<h2 id="112-路径总和"><a href="#112-路径总和" class="headerlink" title="112-路径总和"></a>112-路径总和</h2><p>给你二叉树的根节点 root 和一个表示目标和的整数 targetSum ，判断该树中是否存在 根节点到叶子节点 的路径，这条路径上所有节点值相加等于目标和 targetSum 。</p>
<p><code>DFS</code></p>
<pre><code class="hljs java"><span class="hljs-comment">/**</span>
<span class="hljs-comment"> * Definition for a binary tree node.</span>
<span class="hljs-comment"> * public class TreeNode &#123;</span>
<span class="hljs-comment"> *     int val;</span>
<span class="hljs-comment"> *     TreeNode left;</span>
<span class="hljs-comment"> *     TreeNode right;</span>
<span class="hljs-comment"> *     TreeNode() &#123;&#125;</span>
<span class="hljs-comment"> *     TreeNode(int val) &#123; this.val = val; &#125;</span>
<span class="hljs-comment"> *     TreeNode(int val, TreeNode left, TreeNode right) &#123;</span>
<span class="hljs-comment"> *         this.val = val;</span>
<span class="hljs-comment"> *         this.left = left;</span>
<span class="hljs-comment"> *         this.right = right;</span>
<span class="hljs-comment"> *     &#125;</span>
<span class="hljs-comment"> * &#125;</span>
<span class="hljs-comment"> */</span>
<span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">Solution</span> </span>&#123;
    <span class="hljs-function"><span class="hljs-keyword">public</span> <span class="hljs-keyword">boolean</span> <span class="hljs-title">hasPathSum</span><span class="hljs-params">(TreeNode root, <span class="hljs-keyword">int</span> targetSum)</span> </span>&#123;
        <span class="hljs-keyword">if</span> (root == <span class="hljs-keyword">null</span>) <span class="hljs-keyword">return</span> <span class="hljs-keyword">false</span>;
        <span class="hljs-comment">//符合路径目标和的叶子节点</span>
        <span class="hljs-keyword">if</span> (root.left == <span class="hljs-keyword">null</span> &amp;&amp; root.right == <span class="hljs-keyword">null</span> &amp;&amp; root.val == targetSum) <span class="hljs-keyword">return</span> <span class="hljs-keyword">true</span>;
        <span class="hljs-keyword">boolean</span> left = hasPathSum(root.left, targetSum - root.val);
        <span class="hljs-keyword">boolean</span> right = hasPathSum(root.right, targetSum - root.val);
        <span class="hljs-comment">//左子树和右子树有一个满足路径和就返回true</span>
        <span class="hljs-keyword">if</span> (left || right) <span class="hljs-keyword">return</span> <span class="hljs-keyword">true</span>;
        <span class="hljs-keyword">return</span> <span class="hljs-keyword">false</span>;

    &#125;

    
&#125;</code></pre>
<h2 id="33-搜索旋转排序数组"><a href="#33-搜索旋转排序数组" class="headerlink" title="33-搜索旋转排序数组"></a>33-搜索旋转排序数组</h2><p>整数数组 nums 按升序排列，数组中的值 互不相同 。</p>
<p>在传递给函数之前，nums 在预先未知的某个下标 k（0 &lt;= k &lt; nums.length）上进行了 旋转，使数组变为 [nums[k], nums[k+1], …, nums[n-1], nums[0], nums[1], …, nums[k-1]]（下标 从 0 开始 计数）。例如， [0,1,2,4,5,6,7] 在下标 3 处经旋转后可能变为 [4,5,6,7,0,1,2] 。</p>
<p>给你旋转后的数组 nums 和一个整数 target ，如果 nums 中存在这个目标值 target ，则返回它的索引，否则返回 -1 。</p>
<p><code>找分割点，分别进行二分搜索</code></p>
<pre><code class="hljs java"><span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">Solution</span> </span>&#123;
    <span class="hljs-function"><span class="hljs-keyword">public</span> <span class="hljs-keyword">int</span> <span class="hljs-title">search</span><span class="hljs-params">(<span class="hljs-keyword">int</span>[] nums, <span class="hljs-keyword">int</span> target)</span> </span>&#123;
        <span class="hljs-keyword">int</span> len = nums.length;
        <span class="hljs-keyword">int</span> split = <span class="hljs-number">0</span>;
        <span class="hljs-keyword">for</span> (<span class="hljs-keyword">int</span> i = <span class="hljs-number">0</span>; i &lt; len - <span class="hljs-number">1</span>; i++)&#123;
            <span class="hljs-keyword">if</span> (nums[i + <span class="hljs-number">1</span>] &lt; nums[i])&#123;
                split = i + <span class="hljs-number">1</span>;
                <span class="hljs-keyword">break</span>;
            &#125;
        &#125;
        <span class="hljs-keyword">int</span> res1 = binarySearch(Arrays.copyOfRange(nums, <span class="hljs-number">0</span>, split), target);
        <span class="hljs-keyword">int</span> res2 = binarySearch(Arrays.copyOfRange(nums, split, len), target);
        <span class="hljs-keyword">if</span> (res1 != -<span class="hljs-number">1</span>) <span class="hljs-keyword">return</span> res1;
        <span class="hljs-keyword">if</span> (res2 != -<span class="hljs-number">1</span>) <span class="hljs-keyword">return</span> res2 + split;
        <span class="hljs-keyword">return</span> -<span class="hljs-number">1</span>;

    
    &#125;

    <span class="hljs-function"><span class="hljs-keyword">public</span> <span class="hljs-keyword">int</span> <span class="hljs-title">binarySearch</span><span class="hljs-params">(<span class="hljs-keyword">int</span>[] arr, <span class="hljs-keyword">int</span> k)</span></span>&#123;
        <span class="hljs-keyword">int</span> n = arr.length;
        <span class="hljs-keyword">int</span> left = <span class="hljs-number">0</span>, right = n - <span class="hljs-number">1</span>;
        <span class="hljs-keyword">while</span> (left &lt;= right)&#123;
            <span class="hljs-keyword">int</span> mid = (right - left) / <span class="hljs-number">2</span> + left;
            <span class="hljs-keyword">if</span> (arr[mid] &gt; k)&#123;
                right = mid - <span class="hljs-number">1</span>;
            &#125; <span class="hljs-keyword">else</span> <span class="hljs-keyword">if</span> (arr[mid] &lt; k)&#123;
                left = mid + <span class="hljs-number">1</span>;
            &#125; <span class="hljs-keyword">else</span> &#123;
                <span class="hljs-keyword">return</span> mid;
            &#125;
        &#125;
        <span class="hljs-keyword">return</span> -<span class="hljs-number">1</span>;
    &#125;
&#125;</code></pre>
<p><code>直接进行二分搜素</code></p>
<pre><code class="hljs java"><span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">Solution</span> </span>&#123;
    <span class="hljs-function"><span class="hljs-keyword">public</span> <span class="hljs-keyword">int</span> <span class="hljs-title">search</span><span class="hljs-params">(<span class="hljs-keyword">int</span>[] nums, <span class="hljs-keyword">int</span> target)</span> </span>&#123;
        
        <span class="hljs-keyword">int</span> n = nums.length;
        <span class="hljs-keyword">int</span> left = <span class="hljs-number">0</span>, right = n - <span class="hljs-number">1</span>;
        <span class="hljs-keyword">while</span> (left &lt;= right)&#123;
            <span class="hljs-keyword">int</span> mid = (right - left) / <span class="hljs-number">2</span> + left;
            <span class="hljs-keyword">if</span> (nums[mid] == target) <span class="hljs-keyword">return</span> mid;
            <span class="hljs-comment">//nums[mid]在左半部分</span>
            <span class="hljs-keyword">if</span> (nums[mid] &gt;= nums[left])&#123;
                <span class="hljs-comment">//target的值也在左半部分之间</span>
                <span class="hljs-keyword">if</span> (nums[mid] &gt; target &amp;&amp; nums[left] &lt;= target)&#123;
                    right = mid - <span class="hljs-number">1</span>;
                &#125; <span class="hljs-keyword">else</span> &#123;
                    left = mid + <span class="hljs-number">1</span>;
                &#125;
            &#125; <span class="hljs-keyword">else</span> &#123;
                <span class="hljs-keyword">if</span> (nums[mid] &lt; target &amp;&amp; target &lt;= nums[right])&#123;
                    left = mid + <span class="hljs-number">1</span>;
                &#125; <span class="hljs-keyword">else</span> &#123;
                    right = mid - <span class="hljs-number">1</span>;
                &#125;

            &#125;
        &#125;
        <span class="hljs-keyword">return</span> -<span class="hljs-number">1</span>;
    &#125;
&#125;</code></pre>
<h2 id="239-滑动窗口的最大值"><a href="#239-滑动窗口的最大值" class="headerlink" title="239-滑动窗口的最大值"></a>239-滑动窗口的最大值</h2><p>给你一个整数数组 nums，有一个大小为 k 的滑动窗口从数组的最左侧移动到数组的最右侧。你只可以看到在滑动窗口内的 k 个数字。滑动窗口每次只向右移动一位。</p>
<p>返回滑动窗口中的最大值。</p>
<pre><code class="hljs java"><span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">Solution</span> </span>&#123;
    <span class="hljs-keyword">public</span> <span class="hljs-keyword">int</span>[] maxSlidingWindow(<span class="hljs-keyword">int</span>[] nums, <span class="hljs-keyword">int</span> k) &#123;
        <span class="hljs-comment">// //双指针</span>
        <span class="hljs-comment">// int n = nums.length;</span>
        <span class="hljs-comment">// if (n &lt;= 1) return nums;</span>
        <span class="hljs-comment">// int[] res = new int[n - k + 1];</span>
        <span class="hljs-comment">// int left = 0, right = k - 1;</span>
        <span class="hljs-comment">// while (right &lt; n)&#123;</span>
        <span class="hljs-comment">//     int maxVal = Integer.MIN_VALUE;</span>
        <span class="hljs-comment">//     for (int i = left; i &lt;= right; i++)&#123;</span>
        <span class="hljs-comment">//         maxVal = Math.max(maxVal, nums[i]);</span>
        <span class="hljs-comment">//     &#125;</span>
        <span class="hljs-comment">//     res[left] = maxVal;</span>
        <span class="hljs-comment">//     left++;</span>
        <span class="hljs-comment">//     right++;</span>
        <span class="hljs-comment">// &#125;</span>
        <span class="hljs-comment">// return res;</span>

        <span class="hljs-comment">//最大堆 + 双指针</span>
        <span class="hljs-keyword">int</span> n = nums.length;
        <span class="hljs-keyword">if</span> (n &lt;= <span class="hljs-number">0</span> || k &lt;= <span class="hljs-number">0</span> || n &lt; k) <span class="hljs-keyword">return</span> nums;
        PriorityQueue&lt;Integer&gt; pq = <span class="hljs-keyword">new</span> PriorityQueue&lt;&gt;((a, b) -&gt; (b - a));
        <span class="hljs-comment">//n-k+1为长度为n的数组中大小为k的滑动窗口个数</span>
        <span class="hljs-keyword">int</span>[] res = <span class="hljs-keyword">new</span> <span class="hljs-keyword">int</span>[n - k + <span class="hljs-number">1</span>];
        <span class="hljs-keyword">int</span> right = <span class="hljs-number">0</span>;
        <span class="hljs-keyword">for</span> (; right &lt; k; right++)&#123;
            pq.offer(nums[right]);
        &#125;
        <span class="hljs-keyword">int</span> left = <span class="hljs-number">0</span>;
        <span class="hljs-keyword">while</span> (right &lt; n)&#123;
            res[left++] = pq.peek();
            <span class="hljs-comment">//移除第一个元素</span>
            pq.remove(nums[right - k]);
            <span class="hljs-comment">//nums[right]入堆</span>
            pq.add(nums[right]);
            right++;
        &#125;
        <span class="hljs-comment">//最后一次入堆没有放元素到res中</span>
        res[left] = pq.peek();
        <span class="hljs-keyword">return</span> res;
    &#125;
&#125;</code></pre>
<h2 id="480-滑动窗口中位数"><a href="#480-滑动窗口中位数" class="headerlink" title="480-滑动窗口中位数"></a>480-滑动窗口中位数</h2><p>中位数是有序序列最中间的那个数。如果序列的长度是偶数，则没有最中间的数；此时中位数是最中间的两个数的平均数。</p>
<p>例如：</p>
<ul>
<li>[2,3,4]，中位数是 3</li>
<li>[2,3]，中位数是 (2 + 3) / 2 = 2.5</li>
</ul>
<p>给你一个数组 nums，有一个长度为 k 的窗口从最左端滑动到最右端。窗口中有 k 个数，每次窗口向右移动 1 位。你的任务是找出每次窗口移动后得到的新窗口中元素的中位数，并输出由它们组成的数组。</p>
<img src="/2021/05/03/TX%E7%AC%94%E8%AF%95/image-20210329095743208.png" srcset="/img/loading.gif" class="">
<p><code>堆</code> —— <em>小顶堆存放较大的一半元素， 大顶堆存放较小的一半元素(保证小根堆元素数目不比大根堆少)</em></p>
<pre><code class="hljs java"><span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">Solution</span> </span>&#123;
    PriorityQueue&lt;Integer&gt; minHeap;
    PriorityQueue&lt;Integer&gt; maxHeap;
    <span class="hljs-keyword">public</span> <span class="hljs-keyword">double</span>[] medianSlidingWindow(<span class="hljs-keyword">int</span>[] nums, <span class="hljs-keyword">int</span> k) &#123;
        <span class="hljs-keyword">int</span> n = nums.length;
        <span class="hljs-keyword">double</span>[] res = <span class="hljs-keyword">new</span> <span class="hljs-keyword">double</span>[n - k + <span class="hljs-number">1</span>];
        minHeap  = <span class="hljs-keyword">new</span> PriorityQueue&lt;&gt;((a, b) -&gt; Integer.compare(a, b)); 
        maxHeap = <span class="hljs-keyword">new</span> PriorityQueue&lt;&gt;((a, b) -&gt; Integer.compare(b, a)); 
        <span class="hljs-comment">//小顶堆存放较大的一半元素， 大顶堆存放较小的一半元素(保证小根堆元素数目不比大根堆少)</span>
        <span class="hljs-keyword">for</span> (<span class="hljs-keyword">int</span> i = <span class="hljs-number">0</span>; i &lt; k; i++) minHeap.add(nums[i]);
        <span class="hljs-keyword">for</span> (<span class="hljs-keyword">int</span> i = <span class="hljs-number">0</span>; i &lt; k / <span class="hljs-number">2</span>; i++) maxHeap.add(minHeap.poll());
        res[<span class="hljs-number">0</span>] = getMid();
        <span class="hljs-keyword">for</span> (<span class="hljs-keyword">int</span> i = k; i &lt; n; i++) &#123;
            <span class="hljs-comment">//滑动窗口要删除的元素</span>
            <span class="hljs-keyword">int</span> del = nums[i - k];
            <span class="hljs-comment">//入小顶堆</span>
            <span class="hljs-keyword">if</span> (nums[i] &gt;= minHeap.peek()) &#123;
                minHeap.add(nums[i]);
            &#125; <span class="hljs-keyword">else</span> &#123;
                maxHeap.add(nums[i]);
            &#125;
            <span class="hljs-comment">//要删除的元素在小顶堆</span>
            <span class="hljs-keyword">if</span> (del &gt;= minHeap.peek()) &#123;
                minHeap.remove(del);
            &#125; <span class="hljs-keyword">else</span> &#123;
                maxHeap.remove(del);
            &#125;
            adjust();
            res[i - k + <span class="hljs-number">1</span>] = getMid();
        &#125;
        <span class="hljs-keyword">return</span> res;
    &#125;
    <span class="hljs-function"><span class="hljs-keyword">void</span> <span class="hljs-title">adjust</span><span class="hljs-params">()</span> </span>&#123;
        <span class="hljs-keyword">while</span> (maxHeap.size() &gt; minHeap.size()) minHeap.add(maxHeap.poll());
        <span class="hljs-keyword">while</span> (minHeap.size() - maxHeap.size() &gt; <span class="hljs-number">1</span>) maxHeap.add(minHeap.poll());
    &#125;
    <span class="hljs-function"><span class="hljs-keyword">double</span> <span class="hljs-title">getMid</span><span class="hljs-params">()</span> </span>&#123;
        <span class="hljs-keyword">if</span> (maxHeap.size() == minHeap.size()) &#123;
            <span class="hljs-keyword">return</span> (maxHeap.peek() / <span class="hljs-number">2.0</span>) + (minHeap.peek() / <span class="hljs-number">2.0</span>);
        &#125; <span class="hljs-keyword">else</span> &#123;
            <span class="hljs-keyword">return</span> minHeap.peek() * <span class="hljs-number">1.0</span>;
        &#125;
    &#125;
&#125;
</code></pre>
<h2 id="54-螺旋矩阵"><a href="#54-螺旋矩阵" class="headerlink" title="54-螺旋矩阵"></a>54-螺旋矩阵</h2><p>给你一个 <code>m</code> 行 <code>n</code> 列的矩阵 <code>matrix</code> ，请按照 <strong>顺时针螺旋顺序</strong> ，返回矩阵中的所有元素。</p>
<img src="/2021/05/03/TX%E7%AC%94%E8%AF%95/image-20210323102406007.png" srcset="/img/loading.gif" class="">
<pre><code class="hljs java"><span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">Solution</span> </span>&#123;
    List&lt;Integer&gt; res = <span class="hljs-keyword">new</span> ArrayList&lt;&gt;();
    <span class="hljs-function"><span class="hljs-keyword">public</span> List&lt;Integer&gt; <span class="hljs-title">spiralOrder</span><span class="hljs-params">(<span class="hljs-keyword">int</span>[][] matrix)</span> </span>&#123;
        <span class="hljs-keyword">int</span> m = matrix.length, n = matrix[<span class="hljs-number">0</span>].length;
        <span class="hljs-comment">//记录起止位置</span>
        <span class="hljs-keyword">int</span> rowStart = <span class="hljs-number">0</span>, rowEnd = m - <span class="hljs-number">1</span>;
        <span class="hljs-keyword">int</span> colStart = <span class="hljs-number">0</span>, colEnd = n - <span class="hljs-number">1</span>;
        <span class="hljs-keyword">while</span> (rowStart &lt;= rowEnd &amp;&amp; colStart &lt;= colEnd)&#123;
            <span class="hljs-comment">//向右</span>
            <span class="hljs-keyword">for</span> (<span class="hljs-keyword">int</span> i = colStart; i &lt;= colEnd; i++)&#123;
                res.add(matrix[rowStart][i]);
            &#125;
            <span class="hljs-comment">//少一行</span>
            rowStart++;

            <span class="hljs-comment">//向下</span>
            <span class="hljs-keyword">for</span> (<span class="hljs-keyword">int</span> i = rowStart; i &lt;= rowEnd; i++)&#123;
                res.add(matrix[i][colEnd]);
            &#125;
            <span class="hljs-comment">//少一列</span>
            colEnd--;

            <span class="hljs-comment">//还能向左</span>
            <span class="hljs-keyword">if</span> (rowStart &lt;= rowEnd)&#123;
                <span class="hljs-keyword">for</span> (<span class="hljs-keyword">int</span> i = colEnd; i &gt;= colStart; i--)&#123;
                    res.add(matrix[rowEnd][i]);
                &#125;
                rowEnd--;
            &#125;
            
            <span class="hljs-comment">//还能向上</span>
            <span class="hljs-keyword">if</span> (colStart &lt;= colEnd)&#123;
                <span class="hljs-keyword">for</span> (<span class="hljs-keyword">int</span> i = rowEnd; i &gt;= rowStart; i--)&#123;
                    res.add(matrix[i][colStart]);
                &#125;
                colStart++;
            &#125;
        &#125;
        <span class="hljs-keyword">return</span> res;
    &#125;
&#125;</code></pre>
<h2 id="59-螺旋矩阵Ⅱ"><a href="#59-螺旋矩阵Ⅱ" class="headerlink" title="59-螺旋矩阵Ⅱ"></a>59-螺旋矩阵Ⅱ</h2><p>给你一个正整数 <code>n</code> ，生成一个包含 <code>1</code> 到 <code>n2</code> 所有元素，且元素按顺时针顺序螺旋排列的 <code>n x n</code> 正方形矩阵 <code>matrix</code> 。</p>
<img src="/2021/05/03/TX%E7%AC%94%E8%AF%95/image-20210325145819645.png" srcset="/img/loading.gif" class="">
<pre><code class="hljs java"><span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">Solution</span> </span>&#123;
    <span class="hljs-keyword">public</span> <span class="hljs-keyword">int</span>[][] generateMatrix(<span class="hljs-keyword">int</span> n) &#123;
        <span class="hljs-keyword">int</span>[][] res = <span class="hljs-keyword">new</span> <span class="hljs-keyword">int</span>[n][n];
        <span class="hljs-keyword">int</span> rowStart = <span class="hljs-number">0</span>, rowEnd = n - <span class="hljs-number">1</span>;
        <span class="hljs-keyword">int</span> colStart = <span class="hljs-number">0</span>, colEnd = n - <span class="hljs-number">1</span>;
        <span class="hljs-keyword">int</span> cnt = <span class="hljs-number">1</span>;
        <span class="hljs-keyword">while</span> (rowStart &lt;= rowEnd &amp;&amp; colStart &lt;= colEnd &amp;&amp; cnt &lt;= n * n)
        &#123;
            <span class="hljs-keyword">for</span> (<span class="hljs-keyword">int</span> i = colStart; i &lt;= colEnd; i++)&#123;
                res[rowStart][i] = cnt++;
            &#125;
            rowStart++;

            <span class="hljs-comment">//向下</span>
            <span class="hljs-keyword">for</span> (<span class="hljs-keyword">int</span> i = rowStart; i &lt;= rowEnd; i++)&#123;
                res[i][colEnd] = cnt++;
            &#125;
            colEnd--;

            <span class="hljs-comment">//如果还能向左</span>
            <span class="hljs-keyword">if</span> (rowStart &lt;= rowEnd)&#123;
                <span class="hljs-keyword">for</span> (<span class="hljs-keyword">int</span> i = colEnd; i &gt;= colStart; i--)&#123;
                    res[rowEnd][i] = cnt++;
                &#125;
                rowEnd--;
            &#125;

            <span class="hljs-comment">//如果还能向上</span>
            <span class="hljs-keyword">if</span> (colStart &lt;= colEnd)&#123;
                <span class="hljs-keyword">for</span> (<span class="hljs-keyword">int</span> i = rowEnd; i &gt;= rowStart; i--)&#123;
                    res[i][colStart] = cnt++;
                &#125;
                colStart++;
            &#125;
            
        &#125;
        <span class="hljs-keyword">return</span> res;
            

    &#125;
&#125;</code></pre>
<h2 id="189-旋转数组"><a href="#189-旋转数组" class="headerlink" title="189-旋转数组"></a>189-旋转数组</h2><p>给定一个数组，将数组中的元素向右移动 k 个位置，其中 k 是非负数;</p>
<p><code>进阶</code>：</p>
<p>尽可能想出更多的解决方案，至少有三种不同的方法可以解决这个问题。<br>        你可以使用空间复杂度为 <code>O(1)</code> 的 原地 算法解决这个问题吗？</p>
<pre><code class="hljs java"><span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">Solution</span> </span>&#123;
    <span class="hljs-function"><span class="hljs-keyword">public</span> <span class="hljs-keyword">void</span> <span class="hljs-title">rotate</span><span class="hljs-params">(<span class="hljs-keyword">int</span>[] arr, <span class="hljs-keyword">int</span> k)</span> </span>&#123;
        <span class="hljs-keyword">int</span> len = arr.length;
        <span class="hljs-comment">//k取模，防止比n大时避免多余的旋转</span>
        k %= len;
        <span class="hljs-comment">//先翻转前半部分</span>
        <span class="hljs-keyword">for</span> (<span class="hljs-keyword">int</span> i = <span class="hljs-number">0</span>, j = len - k - <span class="hljs-number">1</span>; i &lt; j; i++, j--)&#123;
            <span class="hljs-keyword">int</span> tmp = arr[i];
            arr[i] = arr[j];
            arr[j] = tmp;
        &#125;
        <span class="hljs-comment">//再翻转后半部分</span>
        <span class="hljs-keyword">for</span> (<span class="hljs-keyword">int</span> i = len - k, j = len - <span class="hljs-number">1</span>; i &lt; j; i++, j--)&#123;
            <span class="hljs-keyword">int</span> tmp = arr[i];
            arr[i] = arr[j];
            arr[j] = tmp;
        &#125;
        <span class="hljs-comment">//最后整体反转</span>
        <span class="hljs-keyword">for</span> (<span class="hljs-keyword">int</span> i = <span class="hljs-number">0</span>, j = len - <span class="hljs-number">1</span>; i &lt; j; i++, j--)&#123;
            <span class="hljs-keyword">int</span> tmp = arr[i];
            arr[i] = arr[j];
            arr[j] = tmp;
        &#125;

    &#125;
&#125;</code></pre>
<h2 id="53-最大子序和-1"><a href="#53-最大子序和-1" class="headerlink" title="53-最大子序和"></a>53-最大子序和</h2><p>给定一个整数数组 <code>nums</code> ，找到一个具有最大和的连续子数组（子数组最少包含一个元素），返回其最大和。</p>
<p><code>动态规划</code> —— dp[i]为以nums[i]结尾的具有最大和的连续子数组</p>
<pre><code class="hljs java"><span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">Solution</span> </span>&#123;
    <span class="hljs-function"><span class="hljs-keyword">public</span> <span class="hljs-keyword">int</span> <span class="hljs-title">maxSubArray</span><span class="hljs-params">(<span class="hljs-keyword">int</span>[] nums)</span> </span>&#123;
        <span class="hljs-keyword">int</span> n = nums.length;
        <span class="hljs-keyword">if</span> (n == <span class="hljs-number">1</span>) <span class="hljs-keyword">return</span> nums[<span class="hljs-number">0</span>]; 
        <span class="hljs-keyword">int</span> sum = nums[<span class="hljs-number">0</span>];

        <span class="hljs-keyword">int</span> dp_0 = nums[<span class="hljs-number">0</span>], dp_1 = <span class="hljs-number">0</span>;
        <span class="hljs-keyword">for</span> (<span class="hljs-keyword">int</span> i = <span class="hljs-number">1</span>; i &lt; n; i++)&#123;
            dp_1 = Math.max(dp_0 + nums[i], nums[i]);
            sum = Math.max(sum, dp_1);
            dp_0 = dp_1;
        &#125;
        <span class="hljs-keyword">return</span> sum;
    &#125;
&#125;</code></pre>
<h2 id="287-寻找重复数"><a href="#287-寻找重复数" class="headerlink" title="287-寻找重复数"></a>287-寻找重复数</h2><p>给定一个包含 n + 1 个整数的数组 nums ，其数字都在 1 到 n 之间（包括 1 和 n），可知至少存在一个重复的整数。</p>
<p>假设 nums 只有 一个重复的整数 ，找出 这个重复的数 。</p>
<p><code>HashSet</code></p>
<pre><code class="hljs java"><span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">Solution</span> </span>&#123;
    <span class="hljs-function"><span class="hljs-keyword">public</span> <span class="hljs-keyword">int</span> <span class="hljs-title">findDuplicate</span><span class="hljs-params">(<span class="hljs-keyword">int</span>[] nums)</span> </span>&#123;
        HashSet&lt;Integer&gt; set = <span class="hljs-keyword">new</span> HashSet&lt;&gt;();
        <span class="hljs-keyword">for</span> (<span class="hljs-keyword">int</span> num : nums)&#123;
            <span class="hljs-keyword">if</span> (set.contains(num))&#123;
                <span class="hljs-keyword">return</span> num;
            &#125; <span class="hljs-keyword">else</span> &#123;
                set.add(num);
            &#125;
        &#125;
        <span class="hljs-keyword">return</span> -<span class="hljs-number">1</span>;
    &#125;
&#125;</code></pre>
<h2 id="494-目标和"><a href="#494-目标和" class="headerlink" title="494-目标和"></a>494-目标和</h2><p>给定一个非负整数数组，a1, a2, …, an, 和一个目标数，S。现在你有两个符号 + 和 -。对于数组中的任意一个整数，你都可以从 + 或 -中选择一个符号添加在前面。</p>
<p>返回可以使最终数组和为目标数 S 的所有添加符号的方法数。</p>
<p><code>回溯法</code></p>
<pre><code class="hljs java"><span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">Solution</span> </span>&#123;
    <span class="hljs-keyword">int</span> cnt = <span class="hljs-number">0</span>;
    <span class="hljs-function"><span class="hljs-keyword">public</span> <span class="hljs-keyword">int</span> <span class="hljs-title">findTargetSumWays</span><span class="hljs-params">(<span class="hljs-keyword">int</span>[] nums, <span class="hljs-keyword">int</span> S)</span> </span>&#123;
        <span class="hljs-keyword">int</span> n = nums.length;
        <span class="hljs-keyword">if</span> (n == <span class="hljs-number">0</span>) <span class="hljs-keyword">return</span> <span class="hljs-number">0</span>;
        backTrack(nums, <span class="hljs-number">0</span>, <span class="hljs-number">0</span>, S);
        <span class="hljs-keyword">return</span> cnt;
    &#125;

    <span class="hljs-function"><span class="hljs-keyword">public</span> <span class="hljs-keyword">void</span> <span class="hljs-title">backTrack</span><span class="hljs-params">(<span class="hljs-keyword">int</span>[] arr, <span class="hljs-keyword">int</span> idx, <span class="hljs-keyword">int</span> sum, <span class="hljs-keyword">int</span> target)</span></span>&#123;
        <span class="hljs-comment">//终止条件 —— 处理到数组末尾</span>
        <span class="hljs-keyword">if</span> (idx == arr.length)&#123;
            <span class="hljs-keyword">if</span> (sum == target)&#123;
                cnt++;
            &#125;
            <span class="hljs-keyword">return</span>;
        &#125;
		
        <span class="hljs-comment">//选择&quot;+&quot;</span>
        sum += arr[idx];
        backTrack(arr, idx + <span class="hljs-number">1</span>, sum, target);
        <span class="hljs-comment">//撤销选择</span>
        sum -= arr[idx];
		
        <span class="hljs-comment">//选择&quot;-&quot;</span>
        sum -= arr[idx];
        backTrack(arr, idx + <span class="hljs-number">1</span>, sum, target);
        <span class="hljs-comment">//撤销选择</span>
        sum += arr[idx];
    &#125;
&#125;</code></pre>
<p><code>动态规划之01背包问题</code></p>
<ul>
<li>假设nums中，正数的和为x，负数的和为y，则S=x-y，sum(nums) = x + y，由此推出x = (S + sum) / 2，问题转化为在nums中寻找若干数使得和为(S+sum)/2，这时问题转化为了01背包问题。</li>
<li>dp[j] —— 填满容量为j的背包，有dp[j]种方法。</li>
<li>状态转移 —— dp[j] = dp[j] + dp[j - num]; 当前填满容量为j的包的方法数 = 之前填满容量为j的包的方法数 + 之前填满容量为j - num的包的方法数。也就是当前数num的加入，可以把之前和为j - num的方法数加入进来。</li>
</ul>
<pre><code class="hljs java"><span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">Solution</span> </span>&#123;

    <span class="hljs-function"><span class="hljs-keyword">public</span> <span class="hljs-keyword">int</span> <span class="hljs-title">findTargetSumWays</span><span class="hljs-params">(<span class="hljs-keyword">int</span>[] nums, <span class="hljs-keyword">int</span> S)</span> </span>&#123;
        <span class="hljs-keyword">int</span> sum = <span class="hljs-number">0</span>;
        <span class="hljs-keyword">for</span> (<span class="hljs-keyword">int</span> num : nums) sum += num;
        <span class="hljs-comment">//不可能有解的情况</span>
        <span class="hljs-comment">//1. 数组中全部数字(正)的和小于S</span>
        <span class="hljs-comment">//2. (sum + S) / 2 为奇数，此时x不是整数</span>
        <span class="hljs-keyword">if</span> (sum &lt; S || (sum + S) % <span class="hljs-number">2</span> == <span class="hljs-number">1</span>)&#123;
            <span class="hljs-keyword">return</span> <span class="hljs-number">0</span>;
        &#125;
        <span class="hljs-keyword">return</span> subset(nums, (sum + S) / <span class="hljs-number">2</span>);
        
    &#125;
    
    <span class="hljs-function"><span class="hljs-keyword">public</span> <span class="hljs-keyword">int</span> <span class="hljs-title">subset</span><span class="hljs-params">(<span class="hljs-keyword">int</span>[] arr, <span class="hljs-keyword">int</span> target)</span></span>&#123;
        <span class="hljs-keyword">int</span>[] dp = <span class="hljs-keyword">new</span> <span class="hljs-keyword">int</span>[target + <span class="hljs-number">1</span>];
        dp[<span class="hljs-number">0</span>] = <span class="hljs-number">1</span>;
        <span class="hljs-keyword">for</span> (<span class="hljs-keyword">int</span> i = <span class="hljs-number">1</span>; i &lt;= arr.length; i++)&#123;
            <span class="hljs-keyword">for</span> (<span class="hljs-keyword">int</span> j = target; j &gt;= <span class="hljs-number">0</span>; j--)&#123;
                <span class="hljs-keyword">if</span> (j &gt;= arr[i - <span class="hljs-number">1</span>])&#123;
                    dp[j] = dp[j] + dp[j - arr[i - <span class="hljs-number">1</span>]];
                &#125; <span class="hljs-keyword">else</span> &#123;
                    dp[j] = dp[j];
                &#125;
            &#125;
        &#125;
        <span class="hljs-keyword">return</span> dp[target];
    &#125;
    
    
&#125;</code></pre>
<h2 id="227-基本计算器Ⅱ"><a href="#227-基本计算器Ⅱ" class="headerlink" title="227-基本计算器Ⅱ"></a>227-基本计算器Ⅱ</h2><p>给你一个字符串表达式 <code>s</code> ，请你实现一个基本计算器来计算并返回它的值。</p>
<p>整数除法仅保留整数部分。</p>
<pre><code class="hljs java"><span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">Solution</span> </span>&#123;
    <span class="hljs-function"><span class="hljs-keyword">public</span> <span class="hljs-keyword">int</span> <span class="hljs-title">calculate</span><span class="hljs-params">(String s)</span> </span>&#123;
        <span class="hljs-keyword">int</span> n = s.length();
        <span class="hljs-keyword">int</span> num = <span class="hljs-number">0</span>;
        <span class="hljs-keyword">char</span> preOps = <span class="hljs-string">&#x27;+&#x27;</span>;
        Deque&lt;Integer&gt; stk = <span class="hljs-keyword">new</span> ArrayDeque&lt;&gt;();
        <span class="hljs-keyword">for</span> (<span class="hljs-keyword">int</span> i = <span class="hljs-number">0</span>; i &lt; n; i++)&#123;
            <span class="hljs-keyword">if</span> (Character.isDigit(s.charAt(i)))&#123;
                num  = num * <span class="hljs-number">10</span> + (s.charAt(i) - <span class="hljs-string">&#x27;0&#x27;</span>);
            &#125;
            <span class="hljs-keyword">if</span> (i == n - <span class="hljs-number">1</span> || !Character.isDigit(s.charAt(i)) &amp;&amp; s.charAt(i) != <span class="hljs-string">&#x27; &#x27;</span>)&#123;
                <span class="hljs-keyword">switch</span>(preOps)&#123;
                    <span class="hljs-keyword">case</span> <span class="hljs-string">&#x27;+&#x27;</span>:
                        stk.push(num);
                        <span class="hljs-keyword">break</span>;
                    <span class="hljs-keyword">case</span> <span class="hljs-string">&#x27;-&#x27;</span>:
                        stk.push(-num);
                        <span class="hljs-keyword">break</span>;
                    <span class="hljs-keyword">case</span> <span class="hljs-string">&#x27;*&#x27;</span>:
                        stk.push(stk.pop() * num);
                        <span class="hljs-keyword">break</span>;
                    <span class="hljs-keyword">case</span> <span class="hljs-string">&#x27;/&#x27;</span>:
                        stk.push(stk.pop() / num);
                        <span class="hljs-keyword">break</span>;
                    
                &#125;
                preOps = s.charAt(i);
                num = <span class="hljs-number">0</span>;
                
            &#125;
        &#125;
        <span class="hljs-keyword">int</span> res = <span class="hljs-number">0</span>;
        <span class="hljs-keyword">while</span> (!stk.isEmpty())&#123;
            res += stk.pop();
        &#125;
        <span class="hljs-keyword">return</span> res;
        
    &#125;
&#125;</code></pre>
<h2 id="43-字符串相乘"><a href="#43-字符串相乘" class="headerlink" title="43-字符串相乘"></a>43-字符串相乘</h2><p>给定两个以字符串形式表示的非负整数 <code>num1</code> 和 <code>num2</code>，返回 <code>num1</code> 和 <code>num2</code> 的乘积，它们的乘积也表示为字符串形式。</p>
<img src="/2021/05/03/TX%E7%AC%94%E8%AF%95/image-20210325141523203.png" srcset="/img/loading.gif" class="">
<pre><code class="hljs java"><span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">Solution</span> </span>&#123;
    <span class="hljs-function"><span class="hljs-keyword">public</span> String <span class="hljs-title">multiply</span><span class="hljs-params">(String num1, String num2)</span> </span>&#123;
        <span class="hljs-keyword">if</span> (num1.equals(<span class="hljs-string">&quot;0&quot;</span>) || num2.equals(<span class="hljs-string">&quot;0&quot;</span>)) &#123;
            <span class="hljs-keyword">return</span> <span class="hljs-string">&quot;0&quot;</span>;
        &#125;
        <span class="hljs-comment">//相乘的总位数为 M + N</span>
        <span class="hljs-keyword">int</span>[] res = <span class="hljs-keyword">new</span> <span class="hljs-keyword">int</span>[num1.length() + num2.length()];
        <span class="hljs-comment">//从尾至头</span>
        <span class="hljs-keyword">for</span> (<span class="hljs-keyword">int</span> i = num1.length() - <span class="hljs-number">1</span>; i &gt;= <span class="hljs-number">0</span>; i--) &#123;
            <span class="hljs-keyword">int</span> n1 = num1.charAt(i) - <span class="hljs-string">&#x27;0&#x27;</span>;
            <span class="hljs-keyword">for</span> (<span class="hljs-keyword">int</span> j = num2.length() - <span class="hljs-number">1</span>; j &gt;= <span class="hljs-number">0</span>; j--) &#123;
                <span class="hljs-keyword">int</span> n2 = num2.charAt(j) - <span class="hljs-string">&#x27;0&#x27;</span>;
                <span class="hljs-keyword">int</span> sum = (res[i + j + <span class="hljs-number">1</span>] + n1 * n2);
                <span class="hljs-comment">//该位累加后的和</span>
                res[i + j + <span class="hljs-number">1</span>] = sum % <span class="hljs-number">10</span>;
                <span class="hljs-comment">//向前进位</span>
                res[i + j] += sum / <span class="hljs-number">10</span>;
            &#125;
        &#125;

        StringBuilder result = <span class="hljs-keyword">new</span> StringBuilder();
        <span class="hljs-keyword">for</span> (<span class="hljs-keyword">int</span> i = <span class="hljs-number">0</span>; i &lt; res.length; i++) &#123;
            <span class="hljs-keyword">if</span> (i == <span class="hljs-number">0</span> &amp;&amp; res[i] == <span class="hljs-number">0</span>) <span class="hljs-keyword">continue</span>;
            result.append(res[i]);
        &#125;
        <span class="hljs-keyword">return</span> result.toString();
    &#125;
        
&#125;</code></pre>
<h2 id="103-二叉树的锯齿形层序遍历"><a href="#103-二叉树的锯齿形层序遍历" class="headerlink" title="103-二叉树的锯齿形层序遍历"></a>103-二叉树的锯齿形层序遍历</h2><p>给定一个二叉树，返回其节点值的锯齿形层序遍历。（即先从左往右，再从右往左进行下一层遍历，以此类推，层与层之间交替进行）。</p>
<p><code>BFS</code>——层次遍历，偶数层的结果翻转一下</p>
<pre><code class="hljs java"><span class="hljs-comment">/**</span>
<span class="hljs-comment"> * Definition for a binary tree node.</span>
<span class="hljs-comment"> * public class TreeNode &#123;</span>
<span class="hljs-comment"> *     int val;</span>
<span class="hljs-comment"> *     TreeNode left;</span>
<span class="hljs-comment"> *     TreeNode right;</span>
<span class="hljs-comment"> *     TreeNode() &#123;&#125;</span>
<span class="hljs-comment"> *     TreeNode(int val) &#123; this.val = val; &#125;</span>
<span class="hljs-comment"> *     TreeNode(int val, TreeNode left, TreeNode right) &#123;</span>
<span class="hljs-comment"> *         this.val = val;</span>
<span class="hljs-comment"> *         this.left = left;</span>
<span class="hljs-comment"> *         this.right = right;</span>
<span class="hljs-comment"> *     &#125;</span>
<span class="hljs-comment"> * &#125;</span>
<span class="hljs-comment"> */</span>
<span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">Solution</span> </span>&#123;
    List&lt;List&lt;Integer&gt;&gt; res = <span class="hljs-keyword">new</span> ArrayList&lt;&gt;();
    <span class="hljs-keyword">public</span> List&lt;List&lt;Integer&gt;&gt; zigzagLevelOrder(TreeNode root) &#123;
        <span class="hljs-keyword">if</span> (root == <span class="hljs-keyword">null</span>) <span class="hljs-keyword">return</span> res;
        Deque&lt;TreeNode&gt; q = <span class="hljs-keyword">new</span> ArrayDeque&lt;&gt;();
        q.offer(root);
        <span class="hljs-keyword">while</span> (!q.isEmpty())&#123;
            <span class="hljs-keyword">int</span> size = q.size();
            List&lt;Integer&gt; tmp = <span class="hljs-keyword">new</span> ArrayList&lt;&gt;();
            <span class="hljs-keyword">for</span> (<span class="hljs-keyword">int</span> i = <span class="hljs-number">0</span>; i &lt; size; i++)&#123;
                TreeNode cur = q.poll();
                tmp.add(cur.val);
                <span class="hljs-keyword">if</span> (cur.left != <span class="hljs-keyword">null</span>) q.offer(cur.left);
                <span class="hljs-keyword">if</span> (cur.right != <span class="hljs-keyword">null</span>) q.offer(cur.right);
            &#125;
            <span class="hljs-keyword">if</span> (res.size() % <span class="hljs-number">2</span> == <span class="hljs-number">1</span>)&#123;
                Collections.reverse(tmp);
            &#125;
            res.add(tmp);

        &#125;
        <span class="hljs-keyword">return</span> res;
    &#125;
&#125;</code></pre>
<h2 id="104-二叉树的最大深度"><a href="#104-二叉树的最大深度" class="headerlink" title="104-二叉树的最大深度"></a>104-二叉树的最大深度</h2><p>给定一个二叉树，找出其最大深度。</p>
<p>二叉树的深度为根节点到最远叶子节点的最长路径上的节点数。</p>
<p><strong>说明:</strong> 叶子节点是指没有子节点的节点。</p>
<p><code>递归</code></p>
<pre><code class="hljs java"><span class="hljs-comment">/**</span>
<span class="hljs-comment"> * Definition for a binary tree node.</span>
<span class="hljs-comment"> * public class TreeNode &#123;</span>
<span class="hljs-comment"> *     int val;</span>
<span class="hljs-comment"> *     TreeNode left;</span>
<span class="hljs-comment"> *     TreeNode right;</span>
<span class="hljs-comment"> *     TreeNode() &#123;&#125;</span>
<span class="hljs-comment"> *     TreeNode(int val) &#123; this.val = val; &#125;</span>
<span class="hljs-comment"> *     TreeNode(int val, TreeNode left, TreeNode right) &#123;</span>
<span class="hljs-comment"> *         this.val = val;</span>
<span class="hljs-comment"> *         this.left = left;</span>
<span class="hljs-comment"> *         this.right = right;</span>
<span class="hljs-comment"> *     &#125;</span>
<span class="hljs-comment"> * &#125;</span>
<span class="hljs-comment"> */</span>
<span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">Solution</span> </span>&#123;
    <span class="hljs-function"><span class="hljs-keyword">public</span> <span class="hljs-keyword">int</span> <span class="hljs-title">maxDepth</span><span class="hljs-params">(TreeNode root)</span> </span>&#123;
        <span class="hljs-keyword">if</span> (root == <span class="hljs-keyword">null</span>) <span class="hljs-keyword">return</span> <span class="hljs-number">0</span>;
        <span class="hljs-keyword">return</span> <span class="hljs-number">1</span> + Math.max(maxDepth(root.left), maxDepth(root.right));
    &#125;
&#125;</code></pre>
<h2 id="剑指Offer65-不用加减乘除做加法"><a href="#剑指Offer65-不用加减乘除做加法" class="headerlink" title="剑指Offer65-不用加减乘除做加法"></a>剑指Offer65-不用加减乘除做加法</h2><p>写一个函数，求两个整数之和，要求在函数体内不得使用 “+”、“-”、“*”、“/” 四则运算符号。</p>
<p><code>位运算</code>——异或和不带进位，所以每次异或的结果与进位再次异或，直到进位为0，此时的和就是两数的和。</p>
<div class="table-container">
<table>
<thead>
<tr>
<th style="text-align:center">位运算</th>
<th style="text-align:center">解释</th>
</tr>
</thead>
<tbody>
<tr>
<td style="text-align:center">num1 ^ num2</td>
<td style="text-align:center">执行加法</td>
</tr>
<tr>
<td style="text-align:center">(num1 &amp; num2) &lt;&lt; 1</td>
<td style="text-align:center">进位</td>
</tr>
</tbody>
</table>
</div>
<pre><code class="hljs java"><span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">Solution</span> </span>&#123;
    <span class="hljs-function"><span class="hljs-keyword">public</span> <span class="hljs-keyword">int</span> <span class="hljs-title">add</span><span class="hljs-params">(<span class="hljs-keyword">int</span> a, <span class="hljs-keyword">int</span> b)</span> </span>&#123;
        <span class="hljs-keyword">int</span> sum = <span class="hljs-number">0</span>, append = <span class="hljs-number">0</span>;
        <span class="hljs-keyword">do</span> &#123;
            sum = a ^ b;
            append = (a &amp; b) &lt;&lt; <span class="hljs-number">1</span>;
            a = sum;
            b = append;
        &#125; <span class="hljs-keyword">while</span> (append != <span class="hljs-number">0</span>);
        <span class="hljs-keyword">return</span> sum;
    &#125;
&#125;</code></pre>
<h2 id="37-解数独"><a href="#37-解数独" class="headerlink" title="37-解数独"></a>37-解数独</h2><p>编写一个程序，通过填充空格来解决数独问题。</p>
<p>一个数独的解法需遵循如下规则：</p>
<ul>
<li>数字 1-9 在每一行只能出现一次。</li>
<li>数字 1-9 在每一列只能出现一次。</li>
<li>数字 1-9 在每一个以粗实线分隔的 3x3 宫内只能出现一次。</li>
<li>空白格用 ‘.’ 表示。</li>
</ul>
<img src="/2021/05/03/TX%E7%AC%94%E8%AF%95/image-20210325144622457.png" srcset="/img/loading.gif" class="">
<p><code>回溯</code></p>
<ul>
<li>只能一行一行地填元素</li>
<li>跳过本来就有数字的位置</li>
<li>做选择时判断选择合不合法， 即行、列、3×3方格内元素不能有重复</li>
<li>找到可行解及时返回</li>
</ul>
<pre><code class="hljs java"><span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">Solution</span> </span>&#123;
    <span class="hljs-function"><span class="hljs-keyword">public</span> <span class="hljs-keyword">void</span> <span class="hljs-title">solveSudoku</span><span class="hljs-params">(<span class="hljs-keyword">char</span>[][] board)</span> </span>&#123;
        backTrack(board, <span class="hljs-number">0</span>, <span class="hljs-number">0</span>);
    &#125;

    <span class="hljs-function"><span class="hljs-keyword">public</span> <span class="hljs-keyword">boolean</span> <span class="hljs-title">backTrack</span><span class="hljs-params">(<span class="hljs-keyword">char</span>[][] arr, <span class="hljs-keyword">int</span> row, <span class="hljs-keyword">int</span> col)</span></span>&#123;
        <span class="hljs-keyword">int</span> m = <span class="hljs-number">9</span>, n = <span class="hljs-number">9</span>;
        <span class="hljs-comment">//穷举到最后一列，则从下一行开始</span>
        <span class="hljs-keyword">if</span> (col == n) <span class="hljs-keyword">return</span> backTrack(arr, row + <span class="hljs-number">1</span>, <span class="hljs-number">0</span>);
        <span class="hljs-comment">//base case， 把所有数字填完了，即找到一个可行解</span>
        <span class="hljs-keyword">if</span> (row == m) <span class="hljs-keyword">return</span> <span class="hljs-keyword">true</span>;
        <span class="hljs-keyword">for</span> (<span class="hljs-keyword">int</span> i = row; i &lt; m; i++)&#123;
            <span class="hljs-keyword">for</span> (<span class="hljs-keyword">int</span> j = col; j &lt; n; j++)&#123;
                <span class="hljs-comment">//board[i][j]上已经有数字了</span>
                <span class="hljs-keyword">if</span> (arr[i][j] != <span class="hljs-string">&#x27;.&#x27;</span>)&#123;
                    <span class="hljs-keyword">return</span> backTrack(arr, i, j + <span class="hljs-number">1</span>);
                &#125;
                <span class="hljs-comment">//在1~9中做选择</span>
                <span class="hljs-keyword">for</span> (<span class="hljs-keyword">char</span> c = <span class="hljs-string">&#x27;1&#x27;</span>; c &lt;= <span class="hljs-string">&#x27;9&#x27;</span>; c++)&#123;
                    <span class="hljs-comment">//选择的数字不合法(违反数独规则)</span>
                    <span class="hljs-keyword">if</span> (!isValid(arr, i, j, c))&#123;
                        <span class="hljs-keyword">continue</span>;
                    &#125;
                    <span class="hljs-comment">//做选择，即填数字</span>
                    arr[i][j] = c;
                    <span class="hljs-comment">//出现可行解，返回true</span>
                    <span class="hljs-keyword">if</span> (backTrack(arr, i, j + <span class="hljs-number">1</span>))&#123;
                        <span class="hljs-keyword">return</span> <span class="hljs-keyword">true</span>;
                    &#125;
                    <span class="hljs-comment">//撤销选择,回置&#x27;.&#x27;</span>
                    arr[i][j] = <span class="hljs-string">&#x27;.&#x27;</span>;
                &#125;
                <span class="hljs-comment">//穷举完1~9仍然没找到可行解，返回false</span>
                <span class="hljs-keyword">return</span> <span class="hljs-keyword">false</span>;
            &#125;
        &#125;
        <span class="hljs-keyword">return</span> <span class="hljs-keyword">false</span>;
    &#125;

    <span class="hljs-function"><span class="hljs-keyword">public</span> <span class="hljs-keyword">boolean</span> <span class="hljs-title">isValid</span><span class="hljs-params">(<span class="hljs-keyword">char</span>[][] matrix, <span class="hljs-keyword">int</span> a, <span class="hljs-keyword">int</span> b, <span class="hljs-keyword">char</span> c)</span></span>&#123;
        <span class="hljs-keyword">for</span> (<span class="hljs-keyword">int</span> i = <span class="hljs-number">0</span>; i &lt; <span class="hljs-number">9</span>; i++)&#123;
            <span class="hljs-keyword">if</span> (matrix[a][i] == c) <span class="hljs-keyword">return</span> <span class="hljs-keyword">false</span>;
            <span class="hljs-keyword">if</span> (matrix[i][b] == c) <span class="hljs-keyword">return</span> <span class="hljs-keyword">false</span>;
            <span class="hljs-comment">// 判断 3 x 3 方框是否存在重复</span>
            <span class="hljs-keyword">if</span> (matrix[(a / <span class="hljs-number">3</span>) * <span class="hljs-number">3</span> + i / <span class="hljs-number">3</span>][(b / <span class="hljs-number">3</span>) * <span class="hljs-number">3</span> + i % <span class="hljs-number">3</span>] == c) <span class="hljs-keyword">return</span> <span class="hljs-keyword">false</span>;
        &#125;
        <span class="hljs-keyword">return</span> <span class="hljs-keyword">true</span>;
    &#125;
&#125;</code></pre>
<h2 id="384-打乱数组"><a href="#384-打乱数组" class="headerlink" title="384-打乱数组"></a>384-打乱数组</h2><p>给你一个整数数组 nums ，设计算法来打乱一个没有重复元素的数组。</p>
<p>实现 Solution class:</p>
<ul>
<li>Solution(int[] nums) 使用整数数组 nums 初始化对象</li>
<li>int[] reset() 重设数组到它的初始状态并返回</li>
<li>int[] shuffle() 返回数组随机打乱后的结果</li>
</ul>
<img src="/2021/05/03/TX%E7%AC%94%E8%AF%95/image-20210325152948253.png" srcset="/img/loading.gif" class="">
<pre><code class="hljs java"></code></pre>
<h2 id="162-寻找峰值"><a href="#162-寻找峰值" class="headerlink" title="162-寻找峰值"></a>162-寻找峰值</h2><p>峰值元素是指其值大于左右相邻值的元素。</p>
<p>给你一个输入数组 nums，找到峰值元素并返回其索引。数组可能包含多个峰值，在这种情况下，返回任何一个峰值所在位置即可。</p>
<p>你可以假设 nums[-1] = nums[n] = -∞。</p>
<p><code>普通解法</code>——时O(N)，空O(1)</p>
<pre><code class="hljs java"><span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">Solution</span> </span>&#123;
    <span class="hljs-function"><span class="hljs-keyword">public</span> <span class="hljs-keyword">int</span> <span class="hljs-title">findPeakElement</span><span class="hljs-params">(<span class="hljs-keyword">int</span>[] nums)</span> </span>&#123;
        <span class="hljs-keyword">int</span> n = nums.length;
        <span class="hljs-keyword">if</span> (n == <span class="hljs-number">1</span>) <span class="hljs-keyword">return</span> <span class="hljs-number">0</span>;
        <span class="hljs-keyword">for</span> (<span class="hljs-keyword">int</span> i = <span class="hljs-number">0</span>; i &lt; n; i++)&#123;
            <span class="hljs-comment">//处理左边界</span>
            <span class="hljs-keyword">if</span> (i == <span class="hljs-number">0</span> &amp;&amp; nums[i + <span class="hljs-number">1</span>] &lt; nums[i])&#123;
                <span class="hljs-keyword">return</span> i;
            &#125;

            <span class="hljs-comment">//处理右边界</span>
            <span class="hljs-keyword">if</span> (i == n - <span class="hljs-number">1</span> &amp;&amp; nums[i - <span class="hljs-number">1</span>] &lt; nums[i])&#123;
                <span class="hljs-keyword">return</span> i;
            &#125;
            
            <span class="hljs-comment">//普通情况</span>
            <span class="hljs-keyword">if</span> (nums[i] &gt; nums[i + <span class="hljs-number">1</span>] &amp;&amp; nums[i] &gt; nums[i + <span class="hljs-number">1</span>])&#123;
                <span class="hljs-keyword">return</span> i;
            &#125;

            
        &#125;
        <span class="hljs-keyword">return</span> -<span class="hljs-number">1</span>;
    &#125;
&#125;</code></pre>
<p><code>二分查找</code>——时O(logN)，空O(1)</p>
<p><code>nums[-1] = nums[n] = -∞</code>，这就代表着 <strong>只要数组中存在一个元素比相邻元素大，那么沿着它一定可以找到一个峰值</strong>。</p>
<pre><code class="hljs java"><span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">Solution</span> </span>&#123;
    <span class="hljs-function"><span class="hljs-keyword">public</span> <span class="hljs-keyword">int</span> <span class="hljs-title">findPeakElement</span><span class="hljs-params">(<span class="hljs-keyword">int</span>[] nums)</span> </span>&#123;
        <span class="hljs-comment">//二分查找</span>
        <span class="hljs-keyword">int</span> left = <span class="hljs-number">0</span>, right = nums.length - <span class="hljs-number">1</span>;
        <span class="hljs-keyword">while</span> (left &lt; right)&#123;
            <span class="hljs-keyword">int</span> mid = (left + right) / <span class="hljs-number">2</span>;
            <span class="hljs-comment">//因为nums[n]为负无穷，因此mid右侧会出现峰值</span>
            <span class="hljs-keyword">if</span> (nums[mid] &lt; nums[mid + <span class="hljs-number">1</span>])&#123;
                left = mid + <span class="hljs-number">1</span>;
            &#125; <span class="hljs-keyword">else</span> &#123;    <span class="hljs-comment">//因为nums[-1]为负无穷，因此mid左侧会出现峰值</span>
                right = mid;
            &#125;
        &#125;
        <span class="hljs-keyword">return</span> left;
    &#125;
&#125;</code></pre>
<h2 id="179-最大数"><a href="#179-最大数" class="headerlink" title="179-最大数"></a>179-最大数</h2><p>给定一组非负整数 nums，重新排列它们每个数字的顺序（每个数字不可拆分）使之组成一个最大的整数。</p>
<p>注意：输出结果可能非常大，所以你需要返回一个字符串而不是整数。</p>
<p><code>自定义比较器</code></p>
<pre><code class="hljs java"><span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">Solution</span> </span>&#123;
    <span class="hljs-function"><span class="hljs-keyword">public</span> String <span class="hljs-title">largestNumber</span><span class="hljs-params">(<span class="hljs-keyword">int</span>[] nums)</span> </span>&#123;
        <span class="hljs-keyword">int</span> n = nums.length;
        <span class="hljs-keyword">if</span> (n == <span class="hljs-number">1</span>) <span class="hljs-keyword">return</span> String.valueOf(nums[<span class="hljs-number">0</span>]);
        String[] arr = <span class="hljs-keyword">new</span> String[n];
        StringBuilder sb = <span class="hljs-keyword">new</span> StringBuilder();

        <span class="hljs-keyword">for</span> (<span class="hljs-keyword">int</span> i = <span class="hljs-number">0</span>; i &lt; n; i++)&#123;
            arr[i] = String.valueOf(nums[i]);
        &#125;
        <span class="hljs-comment">//自定义排序</span>
        Arrays.sort(arr, <span class="hljs-keyword">new</span> Comparator&lt;String&gt;() &#123;
            <span class="hljs-meta">@Override</span>
            <span class="hljs-function"><span class="hljs-keyword">public</span> <span class="hljs-keyword">int</span> <span class="hljs-title">compare</span><span class="hljs-params">(String a, String b)</span> </span>&#123;
                <span class="hljs-keyword">return</span> (b + a).compareTo(a + b);
            &#125;
        &#125;);

        <span class="hljs-comment">//排序后最大的是0</span>
        <span class="hljs-keyword">if</span> (arr[<span class="hljs-number">0</span>].equals(<span class="hljs-string">&quot;0&quot;</span>)) <span class="hljs-keyword">return</span> <span class="hljs-string">&quot;0&quot;</span>;

        <span class="hljs-keyword">for</span> (String s : arr)&#123;
            sb.append(s);
        &#125;
        <span class="hljs-keyword">return</span> sb.toString();
    &#125;
&#125;</code></pre>
<h2 id="剑指Offer40-最小的K个数"><a href="#剑指Offer40-最小的K个数" class="headerlink" title="剑指Offer40-最小的K个数"></a>剑指Offer40-最小的K个数</h2><p>输入整数数组 <code>arr</code> ，找出其中最小的 <code>k</code> 个数。例如，输入4、5、1、6、2、7、3、8这8个数字，则最小的4个数字是1、2、3、4。</p>
<p><code>小根堆</code></p>
<pre><code class="hljs java"><span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">Solution</span> </span>&#123;
    <span class="hljs-keyword">public</span> <span class="hljs-keyword">int</span>[] getLeastNumbers(<span class="hljs-keyword">int</span>[] arr, <span class="hljs-keyword">int</span> k) &#123;
        <span class="hljs-keyword">int</span>[] res = <span class="hljs-keyword">new</span> <span class="hljs-keyword">int</span>[k];
        PriorityQueue&lt;Integer&gt; pq = <span class="hljs-keyword">new</span> PriorityQueue&lt;&gt;();
        <span class="hljs-keyword">for</span> (<span class="hljs-keyword">int</span> num : arr) &#123;
            pq.offer(num);
        &#125;
        <span class="hljs-keyword">int</span> cnt = <span class="hljs-number">0</span>;
        <span class="hljs-keyword">while</span> (cnt &lt; k)&#123;
            res[cnt++] = pq.poll();
        &#125;
        
        <span class="hljs-keyword">return</span> res;
    &#125;
&#125;</code></pre>
<p><code>快排</code></p>
<pre><code class="hljs java"><span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">Solution</span> </span>&#123;
    <span class="hljs-keyword">public</span> <span class="hljs-keyword">int</span>[] getLeastNumbers(<span class="hljs-keyword">int</span>[] arr, <span class="hljs-keyword">int</span> k) &#123;

        <span class="hljs-comment">//快排</span>
        quickSort(arr, <span class="hljs-number">0</span>, arr.length - <span class="hljs-number">1</span>);
        <span class="hljs-keyword">return</span> Arrays.copyOf(arr, k);
    &#125;


    <span class="hljs-comment">//快排</span>
    <span class="hljs-function"><span class="hljs-keyword">public</span> <span class="hljs-keyword">void</span> <span class="hljs-title">quickSort</span><span class="hljs-params">(<span class="hljs-keyword">int</span>[] array, <span class="hljs-keyword">int</span> left, <span class="hljs-keyword">int</span> right)</span></span>&#123;
        <span class="hljs-keyword">if</span> (left &gt;= right) <span class="hljs-keyword">return</span>;
        <span class="hljs-keyword">int</span> i = left, j = right;
        <span class="hljs-keyword">while</span> (i &lt; j)&#123;
            <span class="hljs-keyword">while</span> (i &lt; j &amp;&amp; array[j] &gt;= array[left]) j--;
            <span class="hljs-keyword">while</span> (i &lt; j &amp;&amp; array[i] &lt;= array[left]) i++;
            swap(array, i, j);
        &#125;
        swap(array, i, left);
        <span class="hljs-comment">// 递归左（右）子数组执行哨兵划分</span>
        quickSort(array, left, i - <span class="hljs-number">1</span>);
        quickSort(array, i + <span class="hljs-number">1</span>, right);
    &#125;

    <span class="hljs-comment">//交换函数</span>
    <span class="hljs-function"><span class="hljs-keyword">public</span> <span class="hljs-keyword">void</span> <span class="hljs-title">swap</span><span class="hljs-params">(<span class="hljs-keyword">int</span>[] nums, <span class="hljs-keyword">int</span> i, <span class="hljs-keyword">int</span> j)</span></span>&#123;
        <span class="hljs-keyword">int</span> tmp = nums[i];
        nums[i] = nums[j];
        nums[j] = tmp;
    &#125;
&#125;</code></pre>
<p><code>基于快排的数组划分</code></p>
<pre><code class="hljs java"><span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">Solution</span> </span>&#123;
    <span class="hljs-keyword">public</span> <span class="hljs-keyword">int</span>[] getLeastNumbers(<span class="hljs-keyword">int</span>[] arr, <span class="hljs-keyword">int</span> k) &#123;
    
        <span class="hljs-comment">//基于快排的数组划分</span>
        <span class="hljs-keyword">if</span> (k &gt;= arr.length) <span class="hljs-keyword">return</span> arr;
        <span class="hljs-keyword">return</span> quickSort(arr, k, <span class="hljs-number">0</span>, arr.length - <span class="hljs-number">1</span>);
    &#125;

    <span class="hljs-comment">//基于快排的数组划分</span>
    <span class="hljs-keyword">public</span> <span class="hljs-keyword">int</span>[] quickSort(<span class="hljs-keyword">int</span>[] array, <span class="hljs-keyword">int</span> cnt, <span class="hljs-keyword">int</span> left, <span class="hljs-keyword">int</span> right)&#123;
        <span class="hljs-keyword">int</span> i = left, j = right;
        <span class="hljs-keyword">while</span> (i &lt; j)&#123;
            <span class="hljs-keyword">while</span> (i &lt; j &amp;&amp; array[j] &gt;= array[left]) j--;
            <span class="hljs-keyword">while</span> (i &lt; j &amp;&amp; array[i] &lt;= array[left]) i++;
            swap(array, i, j);
        &#125;
        swap(array, i, left);
        
        <span class="hljs-comment">//前k小的元素在左子数组中</span>
        <span class="hljs-keyword">if</span> (cnt &lt; i) quickSort(array, cnt, left, i - <span class="hljs-number">1</span>);
        <span class="hljs-comment">//前k小的元素在右子数组中</span>
        <span class="hljs-keyword">if</span> (cnt &gt; i) quickSort(array, cnt, i + <span class="hljs-number">1</span>, right);
        <span class="hljs-comment">//k == i， 说明array[k] 即为第 k + 1小的数字，则直接返回数组前 k 个数字即可</span>
        <span class="hljs-keyword">return</span> Arrays.copyOf(array, cnt);
    &#125;

    <span class="hljs-comment">//交换函数</span>
    <span class="hljs-function"><span class="hljs-keyword">public</span> <span class="hljs-keyword">void</span> <span class="hljs-title">swap</span><span class="hljs-params">(<span class="hljs-keyword">int</span>[] nums, <span class="hljs-keyword">int</span> i, <span class="hljs-keyword">int</span> j)</span></span>&#123;
        <span class="hljs-keyword">int</span> tmp = nums[i];
        nums[i] = nums[j];
        nums[j] = tmp;
    &#125;
&#125;</code></pre>
<h2 id="525-连续数组"><a href="#525-连续数组" class="headerlink" title="525-连续数组"></a>525-连续数组</h2><p>给定一个二进制数组, 找到含有相同数量的 0 和 1 的最长连续子数组（的长度）。</p>
<p><code>前缀和 + HashMap</code></p>
<p>把(cnt, i)看作nums[i]的一种状态表示，表明该元素及其前面的全部元素中，1和0的个数差为cnt，如果map不包含key——cnt，则put；包含，则说明此位置和上一个位置这一段区间中，0和1的个数相同。</p>
<pre><code class="hljs java"><span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">Solution</span> </span>&#123;
    <span class="hljs-function"><span class="hljs-keyword">public</span> <span class="hljs-keyword">int</span> <span class="hljs-title">findMaxLength</span><span class="hljs-params">(<span class="hljs-keyword">int</span>[] nums)</span> </span>&#123;
        HashMap&lt;Integer, Integer&gt; map = <span class="hljs-keyword">new</span> HashMap&lt;&gt;();
        map.put(<span class="hljs-number">0</span>, -<span class="hljs-number">1</span>);
        <span class="hljs-keyword">int</span> n = nums.length;
        <span class="hljs-keyword">int</span> maxLen = <span class="hljs-number">0</span>;
        <span class="hljs-keyword">int</span> cnt = <span class="hljs-number">0</span>;
        <span class="hljs-keyword">for</span> (<span class="hljs-keyword">int</span> i = <span class="hljs-number">0</span>; i &lt; n; i++)&#123;
            <span class="hljs-comment">//遇0减1，遇1加1</span>
            cnt += (nums[i] == <span class="hljs-number">1</span> ? <span class="hljs-number">1</span> : -<span class="hljs-number">1</span>);
            <span class="hljs-keyword">if</span> (map.containsKey(cnt))&#123;
                <span class="hljs-comment">//求区间含0、1个数相同的区间的最大长度</span>
                maxLen = Math.max(maxLen, i - map.get(cnt));
            &#125; <span class="hljs-keyword">else</span> &#123;
                map.put(cnt, i);
            &#125;
        &#125;
        <span class="hljs-keyword">return</span> maxLen;
    &#125;
&#125;</code></pre>
<h2 id="15-三数之和"><a href="#15-三数之和" class="headerlink" title="15-三数之和"></a>15-三数之和</h2><p>给你一个包含 n 个整数的数组 nums，判断 nums 中是否存在三个元素 a，b，c ，使得 a + b + c = 0 ？请你找出所有和为 0 且不重复的三元组。</p>
<p>注意：答案中不可以包含重复的三元组。</p>
<p><code>HashMap</code>—— 很难去重，以下代码无法去重</p>
<pre><code class="hljs java"><span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">Solution</span> </span>&#123;
    List&lt;List&lt;Integer&gt;&gt; res = <span class="hljs-keyword">new</span> ArrayList&lt;&gt;();
    <span class="hljs-keyword">public</span> List&lt;List&lt;Integer&gt;&gt; threeSum(<span class="hljs-keyword">int</span>[] nums) &#123;
        <span class="hljs-keyword">int</span> n = nums.length;
        <span class="hljs-comment">//返回[]的情况</span>
        <span class="hljs-keyword">if</span> (n == <span class="hljs-number">0</span> || n == <span class="hljs-number">1</span> &amp;&amp; nums[<span class="hljs-number">0</span>] != <span class="hljs-number">0</span>) <span class="hljs-keyword">return</span> res;
        <span class="hljs-keyword">for</span> (<span class="hljs-keyword">int</span> i = <span class="hljs-number">0</span>; i &lt; n; i++)&#123;
            <span class="hljs-keyword">int</span> sum = nums[i];
            HashMap&lt;Integer, Integer&gt; map = <span class="hljs-keyword">new</span> HashMap&lt;&gt;();
            <span class="hljs-keyword">for</span> (<span class="hljs-keyword">int</span> j = i + <span class="hljs-number">1</span>; j &lt; n; j++)&#123;
                <span class="hljs-keyword">if</span> (map.containsKey(nums[j]))&#123;
                    res.add(<span class="hljs-keyword">new</span> ArrayList&lt;&gt;(Arrays.asList(nums[i], nums[j], nums[map.get(nums[j])])));
                &#125; <span class="hljs-keyword">else</span> &#123;
                    map.put(-sum - nums[j], j);
                &#125;
            &#125;
        &#125;
        <span class="hljs-keyword">return</span> res;
    &#125;
&#125;</code></pre>
<p><code>排序 + 双指针</code></p>
<pre><code class="hljs java"><span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">Solution</span> </span>&#123;
    List&lt;List&lt;Integer&gt;&gt; res = <span class="hljs-keyword">new</span> ArrayList&lt;&gt;();
    <span class="hljs-keyword">public</span> List&lt;List&lt;Integer&gt;&gt; threeSum(<span class="hljs-keyword">int</span>[] nums) &#123;
        <span class="hljs-keyword">int</span> n = nums.length;
        <span class="hljs-comment">//返回[]的情况</span>
        <span class="hljs-keyword">if</span> (n == <span class="hljs-number">0</span> || n == <span class="hljs-number">1</span> &amp;&amp; nums[<span class="hljs-number">0</span>] != <span class="hljs-number">0</span>) <span class="hljs-keyword">return</span> res;
        <span class="hljs-comment">//先排序</span>
        Arrays.sort(nums);
        <span class="hljs-keyword">for</span> (<span class="hljs-keyword">int</span> k = <span class="hljs-number">0</span>; k &lt; n - <span class="hljs-number">2</span>; k++)&#123;
            <span class="hljs-comment">//nums[j] &gt;= nums[i] &gt;= nums[k],如果nums[k] &gt; 0，无解</span>
            <span class="hljs-keyword">if</span>(nums[k] &gt; <span class="hljs-number">0</span>) <span class="hljs-keyword">break</span>;
            <span class="hljs-comment">//跳过此元素nums[k]：因为已经将 nums[k - 1] 的所有可能组合加入到结果中</span>
            <span class="hljs-keyword">if</span>(k &gt; <span class="hljs-number">0</span> &amp;&amp; nums[k] == nums[k - <span class="hljs-number">1</span>]) <span class="hljs-keyword">continue</span>;
            <span class="hljs-comment">//双指针对向移动</span>
            <span class="hljs-keyword">int</span> i = k + <span class="hljs-number">1</span>, j = nums.length - <span class="hljs-number">1</span>;
            <span class="hljs-keyword">while</span>(i &lt; j)&#123;
                <span class="hljs-keyword">int</span> sum = nums[k] + nums[i] + nums[j];
                <span class="hljs-comment">//和过小，左指针右移；和过大，右指针左移</span>
                <span class="hljs-keyword">if</span>(sum &lt; <span class="hljs-number">0</span>)&#123;
                    <span class="hljs-keyword">while</span>(i &lt; j &amp;&amp; nums[i] == nums[++i]);
                &#125; <span class="hljs-keyword">else</span> <span class="hljs-keyword">if</span> (sum &gt; <span class="hljs-number">0</span>) &#123;
                    <span class="hljs-keyword">while</span>(i &lt; j &amp;&amp; nums[j] == nums[--j]);
                &#125; <span class="hljs-keyword">else</span> &#123;
                    res.add(<span class="hljs-keyword">new</span> ArrayList&lt;Integer&gt;(Arrays.asList(nums[k], nums[i], nums[j])));
                    <span class="hljs-comment">//跳过重复的nums[i]和nums[j]</span>
                    <span class="hljs-keyword">while</span>(i &lt; j &amp;&amp; nums[i] == nums[++i]);
                    <span class="hljs-keyword">while</span>(i &lt; j &amp;&amp; nums[j] == nums[--j]);
                &#125;
            &#125;
        &#125;
        <span class="hljs-keyword">return</span> res;
    &#125;
&#125;</code></pre>
<h2 id="31-下一个排列"><a href="#31-下一个排列" class="headerlink" title="31-下一个排列"></a>31-下一个排列</h2><p>实现获取 下一个排列 的函数，算法需要将给定数字序列重新排列成<code>字典序</code>中下一个更大的排列。</p>
<p>如果不存在下一个更大的排列，则将数字重新排列成最小的排列（即<code>升序</code>排列）。</p>
<p>必须 <code>原地</code> 修改，只允许使用额外常数空间。</p>
<ul>
<li>先从后往前查找第一个递减的元素位置i，保证最小幅度增大排列<ul>
<li>找到了，再从后往前找比交换位置元素大的第一个元素，交换；再把交换位置后面的元素改为升序</li>
<li>没找到，说明此时排列已经最大，返回升序序列即可</li>
</ul>
</li>
</ul>
<pre><code class="hljs java"><span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">Solution</span> </span>&#123;
    <span class="hljs-function"><span class="hljs-keyword">public</span> <span class="hljs-keyword">void</span> <span class="hljs-title">nextPermutation</span><span class="hljs-params">(<span class="hljs-keyword">int</span>[] nums)</span> </span>&#123;
        <span class="hljs-keyword">int</span> i = nums.length - <span class="hljs-number">2</span>;
        <span class="hljs-keyword">while</span> (i &gt;= <span class="hljs-number">0</span> &amp;&amp; nums[i] &gt;= nums[i + <span class="hljs-number">1</span>]) &#123;
            i--;
        &#125;
        <span class="hljs-keyword">if</span> (i &gt;= <span class="hljs-number">0</span>) &#123;
            <span class="hljs-keyword">int</span> j = nums.length - <span class="hljs-number">1</span>;
            <span class="hljs-keyword">while</span> (j &gt;= <span class="hljs-number">0</span> &amp;&amp; nums[i] &gt;= nums[j]) &#123;
                j--;
            &#125;
            swap(nums, i, j);
        &#125;
        <span class="hljs-comment">//Arrays.sort(nums, i + 1, nums.length);</span>
        reverse(nums, i + <span class="hljs-number">1</span>);
    &#125;

    <span class="hljs-function"><span class="hljs-keyword">public</span> <span class="hljs-keyword">void</span> <span class="hljs-title">swap</span><span class="hljs-params">(<span class="hljs-keyword">int</span>[] nums, <span class="hljs-keyword">int</span> i, <span class="hljs-keyword">int</span> j)</span> </span>&#123;
        <span class="hljs-keyword">int</span> temp = nums[i];
        nums[i] = nums[j];
        nums[j] = temp;
    &#125;

    <span class="hljs-function"><span class="hljs-keyword">public</span> <span class="hljs-keyword">void</span> <span class="hljs-title">reverse</span><span class="hljs-params">(<span class="hljs-keyword">int</span>[] nums, <span class="hljs-keyword">int</span> start)</span> </span>&#123;
        <span class="hljs-keyword">int</span> left = start, right = nums.length - <span class="hljs-number">1</span>;
        <span class="hljs-keyword">while</span> (left &lt; right) &#123;
            swap(nums, left, right);
            left++;
            right--;
        &#125;
    &#125;
&#125;</code></pre>
<h2 id="199-二叉树的右视图"><a href="#199-二叉树的右视图" class="headerlink" title="199-二叉树的右视图"></a>199-二叉树的右视图</h2><p>给定一棵二叉树，想象自己站在它的右侧，按照从顶部到底部的顺序，返回从右侧所能看到的节点值。</p>
<p><code>深度优先搜索</code></p>
<pre><code class="hljs java"><span class="hljs-comment">/**</span>
<span class="hljs-comment"> * Definition for a binary tree node.</span>
<span class="hljs-comment"> * public class TreeNode &#123;</span>
<span class="hljs-comment"> *     int val;</span>
<span class="hljs-comment"> *     TreeNode left;</span>
<span class="hljs-comment"> *     TreeNode right;</span>
<span class="hljs-comment"> *     TreeNode() &#123;&#125;</span>
<span class="hljs-comment"> *     TreeNode(int val) &#123; this.val = val; &#125;</span>
<span class="hljs-comment"> *     TreeNode(int val, TreeNode left, TreeNode right) &#123;</span>
<span class="hljs-comment"> *         this.val = val;</span>
<span class="hljs-comment"> *         this.left = left;</span>
<span class="hljs-comment"> *         this.right = right;</span>
<span class="hljs-comment"> *     &#125;</span>
<span class="hljs-comment"> * &#125;</span>
<span class="hljs-comment"> */</span>
<span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">Solution</span> </span>&#123;
    List&lt;Integer&gt; res = <span class="hljs-keyword">new</span> ArrayList&lt;&gt;();
    <span class="hljs-function"><span class="hljs-keyword">public</span> List&lt;Integer&gt; <span class="hljs-title">rightSideView</span><span class="hljs-params">(TreeNode root)</span> </span>&#123;
        <span class="hljs-keyword">if</span> (root == <span class="hljs-keyword">null</span>) <span class="hljs-keyword">return</span> res;
        helper(root, <span class="hljs-number">0</span>);
        <span class="hljs-keyword">return</span> res;
    &#125;

    <span class="hljs-function"><span class="hljs-keyword">public</span> <span class="hljs-keyword">void</span> <span class="hljs-title">helper</span><span class="hljs-params">(TreeNode node, <span class="hljs-keyword">int</span> level)</span></span>&#123;
        <span class="hljs-keyword">if</span> (node == <span class="hljs-keyword">null</span>) <span class="hljs-keyword">return</span>;
        <span class="hljs-keyword">if</span> (level == res.size())&#123;
            res.add(node.val);
        &#125;
        <span class="hljs-comment">//先右后左</span>
        helper(node.right, level + <span class="hljs-number">1</span>);
        helper(node.left, level + <span class="hljs-number">1</span>);
    &#125;
&#125;</code></pre>
<h2 id="26-删除有序数组中的重复项"><a href="#26-删除有序数组中的重复项" class="headerlink" title="26-删除有序数组中的重复项"></a>26-删除有序数组中的重复项</h2><p>给你一个有序数组 nums ，请你 原地 删除重复出现的元素，使每个元素 只出现一次 ，返回删除后数组的新长度。</p>
<p>不要使用额外的数组空间，你必须在 原地 修改输入数组 并在使用 O(1) 额外空间的条件下完成。</p>
<pre><code class="hljs java"><span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">Solution</span> </span>&#123;
    <span class="hljs-function"><span class="hljs-keyword">public</span> <span class="hljs-keyword">int</span> <span class="hljs-title">removeDuplicates</span><span class="hljs-params">(<span class="hljs-keyword">int</span>[] nums)</span> </span>&#123;
        <span class="hljs-keyword">int</span> n = nums.length;
        <span class="hljs-keyword">if</span> (n &lt;= <span class="hljs-number">1</span>) <span class="hljs-keyword">return</span> n;
        <span class="hljs-keyword">int</span> cnt = <span class="hljs-number">1</span>;
        <span class="hljs-keyword">for</span> (<span class="hljs-keyword">int</span> i = <span class="hljs-number">1</span>; i &lt; n; i++)&#123;
            <span class="hljs-keyword">if</span> (nums[i - <span class="hljs-number">1</span>] != nums[i])&#123;
                nums[cnt++] = nums[i];
            &#125;
        &#125;
        <span class="hljs-keyword">return</span> cnt;
    &#125;
&#125;</code></pre>
<h2 id="706-设计Hash映射"><a href="#706-设计Hash映射" class="headerlink" title="706-设计Hash映射"></a>706-设计Hash映射</h2><p>不使用任何内建的哈希表库设计一个哈希映射（HashMap）。</p>
<p>实现 MyHashMap 类：</p>
<ul>
<li>MyHashMap() 用空映射初始化对象</li>
<li>void put(int key, int value) 向 HashMap 插入一个键值对 (key, value) 。如果 key 已经存在于映射中，则更新其对应的值 value 。</li>
<li>int get(int key) 返回特定的 key 所映射的 value ；如果映射中不包含 key 的映射，返回 -1 。</li>
<li>void remove(key) 如果映射中存在 key 的映射，则移除 key 和它所对应的 value 。</li>
</ul>
<pre><code class="hljs java"></code></pre>
<h2 id="剑指Offer03-数组中重复的数字"><a href="#剑指Offer03-数组中重复的数字" class="headerlink" title="剑指Offer03-数组中重复的数字"></a>剑指Offer03-数组中重复的数字</h2><p>找出数组中重复的数字。</p>
<p>在一个长度为 n 的数组 nums 里的所有数字都在 0～n-1 的范围内。数组中某些数字是重复的，但不知道有几个数字重复了，也不知道每个数字重复了几次。请找出数组中任意一个重复的数字。</p>
<p><code>原地置换</code> —— 如果没有重复数字，那么正常排序后，数字i应该在下标为i的位置，所以思路是从头扫描数组，遇到下标为i的数字如果不是i的话，（假设为m），那么我们就拿与下标m的数字交换，即换到本来顺序的位置上。在交换过程中，如果有重复的数字发生，那么终止返回ture</p>
<pre><code class="hljs java"><span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">Solution</span> </span>&#123;
    <span class="hljs-function"><span class="hljs-keyword">public</span> <span class="hljs-keyword">int</span> <span class="hljs-title">findRepeatNumber</span><span class="hljs-params">(<span class="hljs-keyword">int</span>[] nums)</span> </span>&#123;
        <span class="hljs-comment">// //HashSet</span>
        <span class="hljs-comment">// int n = nums.length;</span>
        <span class="hljs-comment">// HashSet&lt;Integer&gt; set = new HashSet&lt;&gt;();</span>
        <span class="hljs-comment">// for (int num : nums)&#123;</span>
        <span class="hljs-comment">//     if (set.contains(num))&#123;</span>
        <span class="hljs-comment">//         return num;</span>
        <span class="hljs-comment">//     &#125; else &#123;</span>
        <span class="hljs-comment">//         set.add(num);</span>
        <span class="hljs-comment">//     &#125;</span>
        <span class="hljs-comment">// &#125;</span>
        <span class="hljs-comment">// return -1;</span>

        <span class="hljs-comment">//原地置换，一个萝卜一个坑</span>
        <span class="hljs-keyword">int</span> tmp;
        <span class="hljs-keyword">for</span>(<span class="hljs-keyword">int</span> i = <span class="hljs-number">0</span>; i &lt; nums.length; i++)&#123;
            <span class="hljs-comment">//不在顺序排序的位置上</span>
            <span class="hljs-keyword">while</span> (nums[i] != i)&#123;
                <span class="hljs-comment">//发生相等的情况，把重复数字返回即可</span>
                <span class="hljs-keyword">if</span>(nums[i] == nums[nums[i]])&#123;
                    <span class="hljs-keyword">return</span> nums[i];
                &#125;
                <span class="hljs-comment">//交换到顺序排序的位置上</span>
                tmp = nums[i];
                nums[i] = nums[tmp];
                nums[tmp] = tmp;
            &#125;
        &#125;
        <span class="hljs-keyword">return</span> -<span class="hljs-number">1</span>;
    &#125;
&#125;
</code></pre>
<h2 id="46-全排列"><a href="#46-全排列" class="headerlink" title="46-全排列"></a>46-全排列</h2><p>给定一个 <strong>没有重复</strong> 数字的序列，返回其所有可能的全排列</p>
<p><code>回溯法</code>—— swap()</p>

<pre><code class="hljs java"><span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">Solution</span> </span>&#123;
    List&lt;List&lt;Integer&gt;&gt; res = <span class="hljs-keyword">new</span> ArrayList&lt;&gt;();
    List&lt;Integer&gt; permuteList = <span class="hljs-keyword">new</span> ArrayList&lt;&gt;();

    <span class="hljs-keyword">public</span> List&lt;List&lt;Integer&gt;&gt; permute(<span class="hljs-keyword">int</span>[] nums) &#123;
        <span class="hljs-keyword">for</span> (<span class="hljs-keyword">int</span> i = <span class="hljs-number">0</span>; i &lt; nums.length; i++)&#123;
            permuteList.add(nums[i]);
        &#125;
        backTrack(<span class="hljs-number">0</span>, nums.length);
        <span class="hljs-keyword">return</span> res;
    &#125;

    <span class="hljs-function"><span class="hljs-keyword">public</span> <span class="hljs-keyword">void</span> <span class="hljs-title">backTrack</span><span class="hljs-params">(<span class="hljs-keyword">int</span> begin, <span class="hljs-keyword">int</span> last)</span></span>&#123;
        <span class="hljs-comment">//终止条件</span>
        <span class="hljs-keyword">if</span> (begin == last)&#123;
            res.add(<span class="hljs-keyword">new</span> ArrayList&lt;&gt;(permuteList));
        &#125;
        <span class="hljs-keyword">for</span> (<span class="hljs-keyword">int</span> i = begin; i &lt; last; i++)&#123;
            <span class="hljs-comment">//做选择，即交换</span>
            <span class="hljs-comment">//Collections.swap(permuteList, begin, i);</span>
            swap(begin, i);
            <span class="hljs-comment">//继续回溯</span>
            backTrack(begin + <span class="hljs-number">1</span>, last);
            <span class="hljs-comment">//撤销选择，换回来</span>
            <span class="hljs-comment">//Collections.swap(permuteList, begin, i);</span>
            swap(begin, i);
        &#125;
    &#125;

    <span class="hljs-comment">//交换</span>
    <span class="hljs-function"><span class="hljs-keyword">public</span> <span class="hljs-keyword">void</span> <span class="hljs-title">swap</span><span class="hljs-params">(<span class="hljs-keyword">int</span> j, <span class="hljs-keyword">int</span> k)</span></span>&#123;
        <span class="hljs-keyword">int</span> temp = permuteList.get(j);
        permuteList.set(j, permuteList.get(k));
        permuteList.set(k, temp);
    &#125;
&#125;</code></pre>
<h2 id="200-岛屿数目"><a href="#200-岛屿数目" class="headerlink" title="200-岛屿数目"></a>200-岛屿数目</h2><p>给你一个由 ‘1’（陆地）和 ‘0’（水）组成的的二维网格，请你计算网格中岛屿的数量。</p>
<p>岛屿总是被水包围，并且每座岛屿只能由水平方向和/或竖直方向上相邻的陆地连接形成。</p>
<p>此外，你可以假设该网格的四条边均被水包围。</p>
<p><code>深度优先搜索DFS</code></p>
<pre><code class="hljs java"><span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">Solution</span> </span>&#123;
    <span class="hljs-function"><span class="hljs-keyword">public</span> <span class="hljs-keyword">int</span> <span class="hljs-title">numIslands</span><span class="hljs-params">(<span class="hljs-keyword">char</span>[][] grid)</span> </span>&#123;
        <span class="hljs-keyword">int</span> m = grid.length, n = grid[<span class="hljs-number">0</span>].length;
        <span class="hljs-keyword">int</span> islands = <span class="hljs-number">0</span>;
        <span class="hljs-keyword">for</span> (<span class="hljs-keyword">int</span> i = <span class="hljs-number">0</span>; i &lt; m; i++)&#123;
            <span class="hljs-keyword">for</span> (<span class="hljs-keyword">int</span> j = <span class="hljs-number">0</span>; j &lt; n; j++)&#123;
                <span class="hljs-comment">//碰到1，说明就是新的陆地</span>
                <span class="hljs-keyword">if</span> (grid[i][j] == <span class="hljs-string">&#x27;1&#x27;</span>)&#123;
                    islands++;
                    <span class="hljs-comment">//深度优先搜索，把和(i, j)相连的所在岛的全部陆地的都变为0</span>
                    dfs(grid, i , j);
                &#125;
                
            &#125;
        &#125;
        <span class="hljs-keyword">return</span> islands;
    &#125;

    <span class="hljs-function"><span class="hljs-keyword">public</span> <span class="hljs-keyword">void</span> <span class="hljs-title">dfs</span><span class="hljs-params">(<span class="hljs-keyword">char</span>[][] arr, <span class="hljs-keyword">int</span> i, <span class="hljs-keyword">int</span> j)</span></span>&#123;
        <span class="hljs-comment">//停止搜索的条件</span>
        <span class="hljs-keyword">if</span> (arr[i][j] == <span class="hljs-string">&#x27;0&#x27;</span>) <span class="hljs-keyword">return</span>;
        
        <span class="hljs-comment">//置“0”操作</span>
        arr[i][j] = <span class="hljs-string">&#x27;0&#x27;</span>;

        <span class="hljs-comment">//向上搜索</span>
        <span class="hljs-keyword">if</span> (i - <span class="hljs-number">1</span> &gt;= <span class="hljs-number">0</span>) dfs(arr, i - <span class="hljs-number">1</span>, j);

        <span class="hljs-comment">//向下搜索</span>
        <span class="hljs-keyword">if</span> (i + <span class="hljs-number">1</span> &lt;= arr.length - <span class="hljs-number">1</span>) dfs(arr, i + <span class="hljs-number">1</span>, j);

        <span class="hljs-comment">//向左搜索</span>
        <span class="hljs-keyword">if</span> (j - <span class="hljs-number">1</span> &gt;= <span class="hljs-number">0</span>) dfs(arr, i, j - <span class="hljs-number">1</span>);

        <span class="hljs-comment">//向右搜索</span>
        <span class="hljs-keyword">if</span> (j + <span class="hljs-number">1</span> &lt;= arr[<span class="hljs-number">0</span>].length - <span class="hljs-number">1</span>) dfs(arr, i, j + <span class="hljs-number">1</span>);
    &#125;
&#125;</code></pre>
<h2 id="292-Nim游戏"><a href="#292-Nim游戏" class="headerlink" title="292-Nim游戏"></a>292-Nim游戏</h2><p>你和你的朋友，两个人一起玩 Nim 游戏：</p>
<ul>
<li>桌子上有一堆石头。</li>
<li>你们轮流进行自己的回合，你作为先手。</li>
<li>每一回合，轮到的人拿掉 1 - 3 块石头。</li>
<li>拿掉最后一块石头的人就是获胜者</li>
</ul>
<p>假设你们每一步都是<code>最优解</code>。请编写一个函数，来判断你是否可以在给定石头数量为 n 的情况下赢得游戏。如果可以赢，返回 true；否则，返回 false 。</p>
<p><code>数学</code> —— 每次拿完石头给对手剩4块石头，就稳赢，换言之，在自己的回合中，必须避免石头堆中的石子数为 4 的情况。同样地，如果有五块、六块、或是七块石头，你可以控制自己拿取的石头数，总是恰好给你的对手留下四块石头，使他输掉这场比赛。但是如果石头堆里有八块石头，你就不可避免地会输掉，因为不管你从一堆石头中挑出一块、两块还是三块，你的对手都可以选择三块、两块或一块，以确保在再一次轮到你的时候，你会面对四块石头。</p>
<pre><code class="hljs java"><span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">Solution</span> </span>&#123;
    <span class="hljs-function"><span class="hljs-keyword">public</span> <span class="hljs-keyword">boolean</span> <span class="hljs-title">canWinNim</span><span class="hljs-params">(<span class="hljs-keyword">int</span> n)</span> </span>&#123;
        <span class="hljs-keyword">return</span> (n % <span class="hljs-number">4</span>) != <span class="hljs-number">0</span>;
    &#125;
&#125;</code></pre>
<h2 id="258-各位相加"><a href="#258-各位相加" class="headerlink" title="258-各位相加"></a>258-各位相加</h2><p>给定一个非负整数 <code>num</code>，反复将各个位上的数字相加，直到结果为一位数。</p>
<pre><code class="hljs java"><span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">Solution</span> </span>&#123;
    <span class="hljs-function"><span class="hljs-keyword">public</span> <span class="hljs-keyword">int</span> <span class="hljs-title">addDigits</span><span class="hljs-params">(<span class="hljs-keyword">int</span> num)</span> </span>&#123;
        <span class="hljs-keyword">int</span> res = num;
        <span class="hljs-keyword">while</span> (res &gt;= <span class="hljs-number">10</span>)&#123;
            res = getDigitSum(res);
        &#125;
        <span class="hljs-keyword">return</span> res;
    &#125;

    <span class="hljs-comment">//获取数字各位的和</span>
    <span class="hljs-function"><span class="hljs-keyword">public</span> <span class="hljs-keyword">int</span> <span class="hljs-title">getDigitSum</span><span class="hljs-params">(<span class="hljs-keyword">int</span> n)</span></span>&#123;
        <span class="hljs-keyword">int</span> sum = <span class="hljs-number">0</span>;
        <span class="hljs-keyword">while</span> (n != <span class="hljs-number">0</span>)&#123;
            <span class="hljs-keyword">int</span> digit = n % <span class="hljs-number">10</span>;
            n /= <span class="hljs-number">10</span>;
            sum += digit;
        &#125;
        <span class="hljs-keyword">return</span> sum;
    &#125;
&#125;</code></pre>
<h2 id="378-有序矩阵中第K小的元素"><a href="#378-有序矩阵中第K小的元素" class="headerlink" title="378-有序矩阵中第K小的元素"></a>378-有序矩阵中第K小的元素</h2><p>给你一个 n x n 矩阵 matrix ，其中<code>每行和每列元素均按升序</code>排序，找到矩阵中第 k 小的元素。<br>请注意，它是 排序后 的第 k 小元素，而不是第 k 个 不同 的元素.</p>
<p><code>最小堆</code></p>
<pre><code class="hljs java"><span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">Solution</span> </span>&#123;
    <span class="hljs-function"><span class="hljs-keyword">public</span> <span class="hljs-keyword">int</span> <span class="hljs-title">kthSmallest</span><span class="hljs-params">(<span class="hljs-keyword">int</span>[][] matrix, <span class="hljs-keyword">int</span> k)</span> </span>&#123;
        <span class="hljs-keyword">int</span> m = matrix.length, n = matrix[<span class="hljs-number">0</span>].length;
        <span class="hljs-comment">//最大堆，只留下最小的k个元素</span>
        PriorityQueue&lt;Integer&gt; maxHeap = <span class="hljs-keyword">new</span> PriorityQueue&lt;&gt;(k + <span class="hljs-number">1</span>, (a, b) -&gt; (b - a));
        <span class="hljs-keyword">for</span> (<span class="hljs-keyword">int</span> i = <span class="hljs-number">0</span>; i &lt; m; i++)&#123;
            <span class="hljs-keyword">for</span> (<span class="hljs-keyword">int</span> j = <span class="hljs-number">0</span>; j &lt; n; j++)&#123;
                maxHeap.offer(matrix[i][j]);
                <span class="hljs-keyword">if</span> (maxHeap.size() == k + <span class="hljs-number">1</span>)&#123;
                    maxHeap.poll();
                &#125;
            &#125;
        &#125;
        <span class="hljs-comment">//此时的堆顶元素就是有序矩阵中第K小的元素</span>
        <span class="hljs-keyword">return</span> maxHeap.poll();
    &#125;
&#125;</code></pre>
<p><code>二分搜索</code></p>
<img src="/2021/05/03/TX%E7%AC%94%E8%AF%95/image-20210328094405558.png" srcset="/img/loading.gif" class="">
<pre><code class="hljs java"><span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">Solution</span> </span>&#123;
     <span class="hljs-function"><span class="hljs-keyword">public</span> <span class="hljs-keyword">int</span> <span class="hljs-title">kthSmallest</span><span class="hljs-params">(<span class="hljs-keyword">int</span>[][] matrix, <span class="hljs-keyword">int</span> k)</span> </span>&#123;
        <span class="hljs-keyword">int</span> row = matrix.length;
        <span class="hljs-keyword">int</span> col = matrix[<span class="hljs-number">0</span>].length;
        <span class="hljs-keyword">int</span> left = matrix[<span class="hljs-number">0</span>][<span class="hljs-number">0</span>];
        <span class="hljs-keyword">int</span> right = matrix[row - <span class="hljs-number">1</span>][col - <span class="hljs-number">1</span>];
        <span class="hljs-keyword">while</span> (left &lt; right) &#123;
            <span class="hljs-comment">// 每次循环都保证第K小的数在start~end之间，当start==end，第k小的数就是start</span>
            <span class="hljs-keyword">int</span> mid = (left + right) / <span class="hljs-number">2</span>;
            <span class="hljs-comment">// 找二维矩阵中&lt;=mid的元素总个数</span>
            <span class="hljs-keyword">int</span> count = findNotBiggerThanMid(matrix, mid, row, col);
            <span class="hljs-keyword">if</span> (count &lt; k) &#123;
                <span class="hljs-comment">// 第k小的数在右半部分，且不包含mid</span>
                left = mid + <span class="hljs-number">1</span>;
            &#125; <span class="hljs-keyword">else</span> &#123;
                <span class="hljs-comment">// 第k小的数在左半部分，可能包含mid</span>
                right = mid;
            &#125;
        &#125;
        <span class="hljs-keyword">return</span> right;
    &#125;

    <span class="hljs-function"><span class="hljs-keyword">private</span> <span class="hljs-keyword">int</span> <span class="hljs-title">findNotBiggerThanMid</span><span class="hljs-params">(<span class="hljs-keyword">int</span>[][] matrix, <span class="hljs-keyword">int</span> mid, <span class="hljs-keyword">int</span> row, <span class="hljs-keyword">int</span> col)</span> </span>&#123;
        <span class="hljs-comment">// 以列为单位找，找到每一列最后一个&lt;=mid的数即知道每一列有多少个数&lt;=mid</span>
        <span class="hljs-keyword">int</span> i = row - <span class="hljs-number">1</span>;
        <span class="hljs-keyword">int</span> j = <span class="hljs-number">0</span>;
        <span class="hljs-keyword">int</span> count = <span class="hljs-number">0</span>;
        <span class="hljs-keyword">while</span> (i &gt;= <span class="hljs-number">0</span> &amp;&amp; j &lt; col) &#123;
            <span class="hljs-keyword">if</span> (matrix[i][j] &lt;= mid) &#123;
                <span class="hljs-comment">// 第j列有i+1个元素&lt;=mid</span>
                count += i + <span class="hljs-number">1</span>;
                j++;
            &#125; <span class="hljs-keyword">else</span> &#123;
                <span class="hljs-comment">// 第j列目前的数大于mid，需要继续在当前列往上找</span>
                i--;
            &#125;
        &#125;
        <span class="hljs-keyword">return</span> count;
    &#125;
&#125;</code></pre>
<h2 id="9-回文数"><a href="#9-回文数" class="headerlink" title="9-回文数"></a>9-回文数</h2><p>给你一个整数 x ，如果 x 是一个回文整数，返回 true ；否则，返回 false 。</p>
<p>回文数是指正序（从左向右）和倒序（从右向左）读都是一样的整数。例如，121 是回文，而 123 不是。</p>
<pre><code class="hljs java"><span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">Solution</span> </span>&#123;
    <span class="hljs-function"><span class="hljs-keyword">public</span> <span class="hljs-keyword">boolean</span> <span class="hljs-title">isPalindrome</span><span class="hljs-params">(<span class="hljs-keyword">int</span> x)</span> </span>&#123;
        <span class="hljs-keyword">if</span> (x &lt; <span class="hljs-number">0</span>) <span class="hljs-keyword">return</span> <span class="hljs-keyword">false</span>;
        <span class="hljs-keyword">int</span> cmp = x;
        <span class="hljs-keyword">int</span> sum = <span class="hljs-number">0</span>;
        <span class="hljs-keyword">while</span> (cmp != <span class="hljs-number">0</span>)&#123;
            sum = sum * <span class="hljs-number">10</span> + cmp % <span class="hljs-number">10</span>;
            cmp /= <span class="hljs-number">10</span>;
        &#125;
        <span class="hljs-keyword">return</span> sum == x;
    &#125;
&#125;</code></pre>
<h2 id="5-最长回文子串"><a href="#5-最长回文子串" class="headerlink" title="5-最长回文子串"></a>5-最长回文子串</h2><p>给你一个字符串 <code>s</code>，找到 <code>s</code> 中最长的回文子串。</p>
<p><code>动态规划</code></p>
<pre><code class="hljs java"><span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">Solution</span> </span>&#123;
    <span class="hljs-function"><span class="hljs-keyword">public</span> String <span class="hljs-title">longestPalindrome</span><span class="hljs-params">(String s)</span> </span>&#123;
        <span class="hljs-keyword">int</span> n = s.length();
        <span class="hljs-keyword">if</span> (n &lt;= <span class="hljs-number">1</span>) <span class="hljs-keyword">return</span> s;
        <span class="hljs-comment">//dp[i][j]指示从chars[i]到chars[j]这段子串是否是回文的</span>
        <span class="hljs-keyword">char</span>[] chars = s.toCharArray();
        
        <span class="hljs-keyword">boolean</span> [][] dp = <span class="hljs-keyword">new</span> <span class="hljs-keyword">boolean</span>[n][n];
        <span class="hljs-comment">//记录最大回文子串的起止位置</span>
        <span class="hljs-keyword">int</span> begin = <span class="hljs-number">0</span>, end = <span class="hljs-number">0</span>;
        <span class="hljs-comment">//动态规划</span>
        <span class="hljs-keyword">for</span> (<span class="hljs-keyword">int</span> j = <span class="hljs-number">0</span>; j &lt; n; j++)&#123;
            <span class="hljs-comment">//base case</span>
            dp[j][j] = <span class="hljs-keyword">true</span>;
            <span class="hljs-keyword">for</span> (<span class="hljs-keyword">int</span> i = <span class="hljs-number">0</span>; i &lt; j; i++)&#123;
                <span class="hljs-comment">//子串长为2</span>
                <span class="hljs-keyword">if</span> (i == j - <span class="hljs-number">1</span>)&#123;
                    <span class="hljs-comment">//回文取决于这两个字符是否相等</span>
                    dp[i][j] = chars[i] == chars[j];
                &#125; <span class="hljs-keyword">else</span> &#123;
                    <span class="hljs-comment">//回文取决于dp[i + 1][j - 1]以及最外侧两侧的字符是否相等</span>
                    dp[i][j] = dp[i + <span class="hljs-number">1</span>][j - <span class="hljs-number">1</span>] &amp;&amp; chars[i] == chars[j];
                &#125;
                <span class="hljs-comment">//更新最大回文子串的起止位置</span>
                <span class="hljs-keyword">if</span> (dp[i][j] &amp;&amp; j - i &gt; end - begin)&#123;
                    begin = i;
                    end = j;
                &#125;
            &#125;
        &#125;
        <span class="hljs-keyword">return</span> s.substring(begin, end + <span class="hljs-number">1</span>);

    &#125;
&#125;</code></pre>
<h2 id="516-最长回文子序列"><a href="#516-最长回文子序列" class="headerlink" title="516-最长回文子序列"></a>516-最长回文子序列</h2><p>给定一个字符串 <code>s</code> ，找到其中最长的回文子序列，并返回该序列的长度。可以假设 <code>s</code> 的最大长度为 <code>1000</code> 。</p>
<img src="/2021/05/03/TX%E7%AC%94%E8%AF%95/image-20210328104409216.png" srcset="/img/loading.gif" class="">
<p><code>动态规划</code></p>
<pre><code class="hljs java"><span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">Solution</span> </span>&#123;
    <span class="hljs-function"><span class="hljs-keyword">public</span> <span class="hljs-keyword">int</span> <span class="hljs-title">longestPalindromeSubseq</span><span class="hljs-params">(String s)</span> </span>&#123;
        <span class="hljs-keyword">int</span> n = s.length();
        <span class="hljs-keyword">if</span> (n &lt;= <span class="hljs-number">1</span>) <span class="hljs-keyword">return</span> n;

        <span class="hljs-comment">//dp[i][j]代表从s.charAt(i)到s.charAt(j)的最长回文子序列的长度</span>
        <span class="hljs-keyword">int</span>[][] dp = <span class="hljs-keyword">new</span> <span class="hljs-keyword">int</span>[n][n];

        <span class="hljs-comment">//长度至少为1</span>
        <span class="hljs-keyword">for</span> (<span class="hljs-keyword">int</span> i = <span class="hljs-number">0</span>; i &lt; n; i++)&#123;
            dp[i][i] = <span class="hljs-number">1</span>;
        &#125;

        <span class="hljs-comment">//动态规划，i要从后往前，因为根据我们的dp定义和题目要求，我们要得到dp[0][n - 1]</span>
        <span class="hljs-keyword">for</span> (<span class="hljs-keyword">int</span> i = n - <span class="hljs-number">1</span>; i &gt;= <span class="hljs-number">0</span>; i--)&#123;
            <span class="hljs-keyword">for</span> (<span class="hljs-keyword">int</span> j = i + <span class="hljs-number">1</span>; j &lt; n; j++)&#123;
                <span class="hljs-keyword">if</span> (s.charAt(i) == s.charAt(j))&#123;
                    <span class="hljs-comment">//长度+2</span>
                    dp[i][j] = dp[i + <span class="hljs-number">1</span>][j - <span class="hljs-number">1</span>] + <span class="hljs-number">2</span>;
                &#125; <span class="hljs-keyword">else</span> &#123;
                    <span class="hljs-comment">//区间左边界向右进1或者右区间向左退1</span>
                    dp[i][j] = Math.max(dp[i + <span class="hljs-number">1</span>][j], dp[i][j - <span class="hljs-number">1</span>]);
                &#125;
            &#125;
        &#125;

        <span class="hljs-keyword">return</span> dp[<span class="hljs-number">0</span>][n - <span class="hljs-number">1</span>];
    &#125;
&#125;</code></pre>
<h2 id="994-腐烂的橘子"><a href="#994-腐烂的橘子" class="headerlink" title="994-腐烂的橘子"></a>994-腐烂的橘子</h2><p>在给定的网格中，每个单元格可以有以下三个值之一：</p>
<ul>
<li>值 0 代表空单元格；</li>
<li>值 1 代表新鲜橘子；</li>
<li>值 2 代表腐烂的橘子；</li>
<li>每分钟，任何与腐烂的橘子（在 4 个正方向上）相邻的新鲜橘子都会腐烂。</li>
</ul>
<p>返回直到单元格中没有新鲜橘子为止所必须经过的最小分钟数。如果不可能，返回 -1。</p>
<img src="/2021/05/03/TX%E7%AC%94%E8%AF%95/image-20210328105332143.png" srcset="/img/loading.gif" class="">
<p>与岛屿类的题目很像，都是<code>用不同数字代表状态</code>，每次遍历矩阵时改变符合条件的元素的值，这里腐烂的橘子代表“2”，它会传染相邻的值为“1”的新鲜橘子，最终要求出感染的时间，所以可以在感染新鲜的橘子时，将值为“1”的新鲜橘子修改为感染对应的第几趟（这个橘子是第几趟感染的），比如被“2”的橘子感染，则值变为“3”（第一趟被感染，3-2），被“3”的橘子感染，则值变为“4”（第二趟被感染，4-2），依此类推，最后得到的数值index-3就是被感染的时间了。</p>
<pre><code class="hljs java"><span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">Solution</span> </span>&#123;
    <span class="hljs-keyword">int</span> minutes = <span class="hljs-number">3</span>;

    <span class="hljs-function"><span class="hljs-keyword">public</span> <span class="hljs-keyword">int</span> <span class="hljs-title">orangesRotting</span><span class="hljs-params">(<span class="hljs-keyword">int</span>[][] grid)</span> </span>&#123;
        <span class="hljs-keyword">int</span> m = grid.length, n = grid[<span class="hljs-number">0</span>].length;
        <span class="hljs-keyword">while</span> (<span class="hljs-keyword">true</span>)&#123;
            <span class="hljs-comment">// 这里flag是循环跳出的条件，如果这一次while循环中没有橘子被感染，break;</span>
            <span class="hljs-keyword">boolean</span> flag = <span class="hljs-keyword">false</span>;
            <span class="hljs-keyword">for</span> (<span class="hljs-keyword">int</span> i = <span class="hljs-number">0</span>; i &lt;= m - <span class="hljs-number">1</span>; i++)&#123;
                <span class="hljs-keyword">for</span> (<span class="hljs-keyword">int</span> j = <span class="hljs-number">0</span>; j &lt;= n - <span class="hljs-number">1</span>; j++)&#123;
                    <span class="hljs-comment">//遇到的腐烂橘子</span>
                    <span class="hljs-keyword">if</span> (grid[i][j] == minutes - <span class="hljs-number">1</span>)&#123;
                        <span class="hljs-comment">//四个方向如果还有新鲜橘子就让它腐烂</span>
                        <span class="hljs-keyword">if</span> (i - <span class="hljs-number">1</span> &gt;= <span class="hljs-number">0</span> &amp;&amp; grid[i - <span class="hljs-number">1</span>][j] == <span class="hljs-number">1</span>) &#123;
                            grid[i - <span class="hljs-number">1</span>][j] = minutes;
                            flag = <span class="hljs-keyword">true</span>;
                        &#125;
                        <span class="hljs-keyword">if</span> (i + <span class="hljs-number">1</span> &lt;= grid.length - <span class="hljs-number">1</span> &amp;&amp; grid[i + <span class="hljs-number">1</span>][j] == <span class="hljs-number">1</span>) &#123;
                            grid[i + <span class="hljs-number">1</span>][j] = minutes;
                            flag = <span class="hljs-keyword">true</span>;
                        &#125;
                        <span class="hljs-keyword">if</span> (j - <span class="hljs-number">1</span> &gt;= <span class="hljs-number">0</span> &amp;&amp; grid[i][j - <span class="hljs-number">1</span>] == <span class="hljs-number">1</span>) &#123;
                            grid[i][j - <span class="hljs-number">1</span>] = minutes;
                            flag = <span class="hljs-keyword">true</span>;
                        &#125;
                        <span class="hljs-keyword">if</span> (j + <span class="hljs-number">1</span> &lt;= grid[<span class="hljs-number">0</span>].length - <span class="hljs-number">1</span> &amp;&amp; grid[i][j + <span class="hljs-number">1</span>] == <span class="hljs-number">1</span>) &#123;
                            grid[i][j + <span class="hljs-number">1</span>] = minutes;
                            flag = <span class="hljs-keyword">true</span>;
                        &#125;
                    &#125;
                &#125;
            &#125;
            <span class="hljs-comment">//橘子全部腐烂或者所有橘子没有完全腐烂，退出循环</span>
            <span class="hljs-keyword">if</span> (!flag) <span class="hljs-keyword">break</span>;
            <span class="hljs-comment">//一轮结束还有橘子未腐烂，分钟数+1</span>
            minutes++;
        &#125;

        <span class="hljs-comment">//添加一轮检查，查看是全部腐烂的情况还是没完全腐烂的情况</span>
        <span class="hljs-keyword">for</span> (<span class="hljs-keyword">int</span> i = <span class="hljs-number">0</span>; i &lt; m; i++)&#123;
            <span class="hljs-keyword">for</span> (<span class="hljs-keyword">int</span> j = <span class="hljs-number">0</span>; j &lt; n; j++)&#123;
                <span class="hljs-comment">//还有新鲜橘子，则返回-1</span>
                <span class="hljs-keyword">if</span> (grid[i][j] == <span class="hljs-number">1</span>)&#123;
                    <span class="hljs-keyword">return</span> -<span class="hljs-number">1</span>;
                &#125;
            &#125;
        &#125;
        <span class="hljs-comment">//否则返回分钟数，即minutes减去基数3</span>
        <span class="hljs-keyword">return</span> minutes - <span class="hljs-number">3</span>;
        
    &#125;

&#125;</code></pre>
<h2 id="48-旋转图像"><a href="#48-旋转图像" class="headerlink" title="48-旋转图像"></a>48-旋转图像</h2><p>给定一个 n × n 的二维矩阵 matrix 表示一个图像。请你将图像<code>顺时针旋转 90 度</code>。</p>
<p>你必须在<code>原地</code>旋转图像，这意味着你需要直接修改输入的二维矩阵。请不要 使用另一个矩阵来旋转图像。</p>
<img src="/2021/05/03/TX%E7%AC%94%E8%AF%95/image-20210329143029666.png" srcset="/img/loading.gif" class="">
<p><code>90度旋转</code>：</p>
<p>顺时针替换即可</p>
<img src="/2021/05/03/TX%E7%AC%94%E8%AF%95/image-20210329145727697.png" srcset="/img/loading.gif" class="">
<pre><code class="hljs java"><span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">Solution</span> </span>&#123;
    <span class="hljs-function"><span class="hljs-keyword">public</span> <span class="hljs-keyword">void</span> <span class="hljs-title">rotate</span><span class="hljs-params">(<span class="hljs-keyword">int</span>[][] matrix)</span> </span>&#123;
        <span class="hljs-keyword">int</span> m = matrix.length, n = matrix[<span class="hljs-number">0</span>].length;
        <span class="hljs-comment">//只需要一半进行顺时针轮转交换</span>
        <span class="hljs-keyword">for</span> (<span class="hljs-keyword">int</span> i = <span class="hljs-number">0</span>; i &lt; (n + <span class="hljs-number">1</span>) / <span class="hljs-number">2</span>; i++)&#123;
            <span class="hljs-keyword">for</span> (<span class="hljs-keyword">int</span> j = <span class="hljs-number">0</span>; j &lt; n / <span class="hljs-number">2</span>; j++)&#123;
                <span class="hljs-comment">// temp = 7</span>
                <span class="hljs-keyword">int</span> temp = matrix[n - <span class="hljs-number">1</span> - j][i];
                <span class="hljs-comment">// 9 -&gt; 7(同一行)</span>
                matrix[n - <span class="hljs-number">1</span> - j][i] = matrix[n - <span class="hljs-number">1</span> - i][n - <span class="hljs-number">1</span> - j];
                <span class="hljs-comment">// 3 -&gt; 9(同一列))</span>
                matrix[n - <span class="hljs-number">1</span> - i][n - <span class="hljs-number">1</span> - j] = matrix[j][n - <span class="hljs-number">1</span> - i];
                <span class="hljs-comment">// 1 -&gt; 3(同一行)</span>
                matrix[j][n - <span class="hljs-number">1</span> - i] = matrix[i][j];
                <span class="hljs-comment">// temp = 7 -&gt; 1</span>
                matrix[i][j] = temp;
            &#125;
        &#125;

    &#125;
&#125;</code></pre>
<h2 id="1044-最长重复子串"><a href="#1044-最长重复子串" class="headerlink" title="1044-最长重复子串"></a>1044-最长重复子串</h2><p>给出一个字符串 S，考虑其所有重复子串（S 的<code>连续子串</code>，出现<code>两次或多次</code>，可能会有重叠）。</p>
<p>返回任何具有最长可能长度的重复子串。（如果 S 不含重复子串，那么答案为 “”。）</p>
<p><code>HashSet</code>——超时</p>
<pre><code class="hljs java"><span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">Solution</span> </span>&#123;
    <span class="hljs-function"><span class="hljs-keyword">public</span> String <span class="hljs-title">longestDupSubstring</span><span class="hljs-params">(String s)</span> </span>&#123;
        <span class="hljs-keyword">int</span> len = s.length();
        Set&lt;String&gt; set = <span class="hljs-keyword">new</span> HashSet&lt;&gt;();
        <span class="hljs-keyword">int</span> maxLen = <span class="hljs-number">0</span>;
        String res = <span class="hljs-string">&quot;&quot;</span>;
        <span class="hljs-keyword">for</span> (<span class="hljs-keyword">int</span> i = <span class="hljs-number">0</span>; i &lt; len; i++)&#123;
            <span class="hljs-keyword">for</span> (<span class="hljs-keyword">int</span> j = i + <span class="hljs-number">1</span>; j &lt;= len; j++)&#123;
                <span class="hljs-comment">//获取子串</span>
                String temp = s.substring(i, j);
                <span class="hljs-comment">//重复性和最大性判断</span>
                <span class="hljs-keyword">if</span> (set.contains(temp) &amp;&amp; j - i &gt; maxLen)&#123;
                    <span class="hljs-comment">//更新最大重复子串长度</span>
                    maxLen = j - i;
                    res = temp;
                &#125; <span class="hljs-keyword">else</span> &#123;
                    set.add(temp);
                &#125;
            &#125;
        &#125;
        <span class="hljs-keyword">return</span> res;

    &#125;
&#125;</code></pre>
<h2 id="11-盛最多水的容器"><a href="#11-盛最多水的容器" class="headerlink" title="11-盛最多水的容器"></a>11-盛最多水的容器</h2><p>给你 n 个非负整数 a1，a2，…，an，每个数代表坐标中的一个点 (i, ai) 。在坐标内画 n 条垂直线，垂直线 i 的两个端点分别为 (i, ai) 和 (i, 0) 。找出其中的两条线，使得它们与 x 轴共同构成的容器可以容纳最多的水。</p>
<p>说明：你不能倾斜容器。</p>
<img src="/2021/05/03/TX%E7%AC%94%E8%AF%95/image-20210330085345954.png" srcset="/img/loading.gif" class="">
<p><code>双指针</code>——<em>只有当前首尾指针指向位置的height小于h(等于是一开始的情况)，此时移动指针才有可能使maxVolume增大</em></p>
<pre><code class="hljs java"><span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">Solution</span> </span>&#123;
    <span class="hljs-function"><span class="hljs-keyword">public</span> <span class="hljs-keyword">int</span> <span class="hljs-title">maxArea</span><span class="hljs-params">(<span class="hljs-keyword">int</span>[] height)</span> </span>&#123;
        <span class="hljs-keyword">int</span> n = height.length;
        <span class="hljs-keyword">if</span> (n &lt;= <span class="hljs-number">1</span>) <span class="hljs-keyword">return</span> <span class="hljs-number">0</span>;
        <span class="hljs-keyword">int</span> maxVolume = <span class="hljs-number">0</span>;
        <span class="hljs-comment">//首尾指针</span>
        <span class="hljs-keyword">int</span> leftPtr = <span class="hljs-number">0</span>, rightPtr = n - <span class="hljs-number">1</span>;
        <span class="hljs-keyword">while</span> (leftPtr &lt; rightPtr)&#123;
            <span class="hljs-comment">//高度h</span>
            <span class="hljs-keyword">int</span> h = Math.min(height[leftPtr], height[rightPtr]);
            <span class="hljs-comment">//更新最大容量</span>
            maxVolume = Math.max(maxVolume, (rightPtr - leftPtr) * h);
            
            <span class="hljs-comment">//若当前首尾指针指向位置的height小于h(等于是一开始的情况)，此时移动指针才有可能使maxVolume增大</span>
            <span class="hljs-keyword">while</span> (height[leftPtr] &lt;= h &amp;&amp; (leftPtr &lt; rightPtr)) leftPtr++;
            <span class="hljs-keyword">while</span> (height[rightPtr] &lt;= h &amp;&amp; (leftPtr &lt; rightPtr)) rightPtr--;
        &#125;
        <span class="hljs-keyword">return</span> maxVolume;
    &#125;
&#125;</code></pre>
<h2 id="297-二叉树的序列化与反序列化"><a href="#297-二叉树的序列化与反序列化" class="headerlink" title="297-二叉树的序列化与反序列化"></a>297-二叉树的序列化与反序列化</h2><p>序列化是将一个数据结构或者对象转换为连续的比特位的操作，进而可以将转换后的数据存储在一个文件或者内存中，同时也可以通过网络传输到另一个计算机环境，采取相反方式重构得到原数据。</p>
<p>请设计一个算法来实现二叉树的序列化与反序列化。这里不限定你的序列 / 反序列化算法执行逻辑，你只需要保证一个二叉树可以被序列化为一个字符串并且将这个字符串反序列化为原始的树结构。</p>
<img src="/2021/05/03/TX%E7%AC%94%E8%AF%95/image-20210330091251174.png" srcset="/img/loading.gif" class="">
<p><code>层序遍历</code></p>
<pre><code class="hljs java"><span class="hljs-comment">/**</span>
<span class="hljs-comment"> * Definition for a binary tree node.</span>
<span class="hljs-comment"> * public class TreeNode &#123;</span>
<span class="hljs-comment"> *     int val;</span>
<span class="hljs-comment"> *     TreeNode left;</span>
<span class="hljs-comment"> *     TreeNode right;</span>
<span class="hljs-comment"> *     TreeNode(int x) &#123; val = x; &#125;</span>
<span class="hljs-comment"> * &#125;</span>
<span class="hljs-comment"> */</span>
<span class="hljs-keyword">public</span> <span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">Codec</span> </span>&#123;

    <span class="hljs-comment">// Encodes a tree to a single string.</span>
    <span class="hljs-function"><span class="hljs-keyword">public</span> String <span class="hljs-title">serialize</span><span class="hljs-params">(TreeNode root)</span> </span>&#123;
        <span class="hljs-keyword">if</span> (root == <span class="hljs-keyword">null</span>) <span class="hljs-keyword">return</span> <span class="hljs-string">&quot;[]&quot;</span>;
        <span class="hljs-comment">//层次遍历</span>
        StringBuilder sb = <span class="hljs-keyword">new</span> StringBuilder(<span class="hljs-string">&quot;[&quot;</span>);
        Queue&lt;TreeNode&gt; q = <span class="hljs-keyword">new</span> LinkedList&lt;&gt;();
        q.offer(root);
        <span class="hljs-keyword">while</span> (!q.isEmpty())&#123;
            <span class="hljs-keyword">int</span> size = q.size();
            <span class="hljs-keyword">for</span> (<span class="hljs-keyword">int</span> i = <span class="hljs-number">0</span>; i &lt; size; i++)&#123;
                TreeNode node = q.poll();
                <span class="hljs-keyword">if</span> (node != <span class="hljs-keyword">null</span>) &#123;
                    sb.append(node.val);
                    q.offer(node.left);
                    q.offer(node.right);
                &#125; <span class="hljs-keyword">else</span> &#123;
                    sb.append(<span class="hljs-string">&quot;null&quot;</span>);
                &#125;
                sb.append(<span class="hljs-string">&quot;,&quot;</span>);
            &#125;
        &#125;
        <span class="hljs-keyword">return</span> sb.deleteCharAt(sb.length() - <span class="hljs-number">1</span>).append(<span class="hljs-string">&quot;]&quot;</span>).toString();
    &#125;

    <span class="hljs-comment">// Decodes your encoded data to tree.</span>
    <span class="hljs-function"><span class="hljs-keyword">public</span> TreeNode <span class="hljs-title">deserialize</span><span class="hljs-params">(String data)</span> </span>&#123;
        <span class="hljs-keyword">if</span> (data == <span class="hljs-keyword">null</span> || <span class="hljs-string">&quot;[]&quot;</span>.equals(data)) &#123;
            <span class="hljs-keyword">return</span> <span class="hljs-keyword">null</span>;
        &#125;
        String[] splitData = data.substring(<span class="hljs-number">1</span>, data.length() - <span class="hljs-number">1</span>).split(<span class="hljs-string">&quot;,&quot;</span>);
        <span class="hljs-keyword">int</span> len = splitData.length;
        TreeNode root = <span class="hljs-keyword">new</span> TreeNode(Integer.parseInt(splitData[<span class="hljs-number">0</span>]));
        Deque&lt;TreeNode&gt; q = <span class="hljs-keyword">new</span> ArrayDeque&lt;&gt;();
        q.offer(root);
        <span class="hljs-keyword">int</span> idx = <span class="hljs-number">1</span>;
        <span class="hljs-keyword">while</span> (!q.isEmpty() &amp;&amp; idx &lt; len)&#123;
            TreeNode node = q.poll();
            <span class="hljs-keyword">if</span> (!<span class="hljs-string">&quot;null&quot;</span>.equals(splitData[idx]))&#123;
                node.left = <span class="hljs-keyword">new</span> TreeNode(Integer.parseInt(splitData[idx]));
                q.offer(node.left);
            &#125;
            idx++;
            <span class="hljs-keyword">if</span> (!<span class="hljs-string">&quot;null&quot;</span>.equals(splitData[idx]))&#123;
                node.right = <span class="hljs-keyword">new</span> TreeNode(Integer.parseInt(splitData[idx]));
                q.offer(node.right);
            &#125;
            idx++;
        &#125;
        <span class="hljs-keyword">return</span> root;
    &#125;

&#125;

<span class="hljs-comment">// Your Codec object will be instantiated and called as such:</span>
<span class="hljs-comment">// Codec codec = new Codec();</span>
<span class="hljs-comment">// codec.deserialize(codec.serialize(root));</span></code></pre>
<h2 id="72-编辑距离"><a href="#72-编辑距离" class="headerlink" title="72-编辑距离"></a>72-编辑距离</h2><p>给你两个单词 word1 和 word2，请你计算出将 word1 转换成 word2 所使用的最少操作数 。</p>
<p>你可以对一个单词进行如下三种操作：</p>
<ul>
<li>插入一个字符</li>
<li>删除一个字符</li>
<li>替换一个字符</li>
</ul>
<img src="/2021/05/03/TX%E7%AC%94%E8%AF%95/image-20210330101000806.png" srcset="/img/loading.gif" class="">
<pre><code class="hljs java"><span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">Solution</span> </span>&#123;
    <span class="hljs-function"><span class="hljs-keyword">public</span> <span class="hljs-keyword">int</span> <span class="hljs-title">minDistance</span><span class="hljs-params">(String word1, String word2)</span> </span>&#123;
        <span class="hljs-keyword">int</span> al = word1.length(), bl = word2.length();
        <span class="hljs-keyword">int</span> [][] dp = <span class="hljs-keyword">new</span> <span class="hljs-keyword">int</span>[al + <span class="hljs-number">1</span>][bl + <span class="hljs-number">1</span>];
        <span class="hljs-comment">// base case</span>
        <span class="hljs-keyword">for</span>(<span class="hljs-keyword">int</span> i = <span class="hljs-number">1</span>; i &lt;= al; i++) 
            dp[i][<span class="hljs-number">0</span>] = i;
        <span class="hljs-keyword">for</span>(<span class="hljs-keyword">int</span> j = <span class="hljs-number">1</span>; j &lt;= bl; j++) 
            dp[<span class="hljs-number">0</span>][j] = j;
        <span class="hljs-keyword">for</span>(<span class="hljs-keyword">int</span> i = <span class="hljs-number">1</span>; i &lt;= al; i++) &#123;
            <span class="hljs-keyword">for</span>(<span class="hljs-keyword">int</span> j = <span class="hljs-number">1</span>; j &lt;= bl; j++) &#123;
                <span class="hljs-comment">// state update</span>
                <span class="hljs-keyword">if</span> (word1.charAt(i - <span class="hljs-number">1</span>) == word2.charAt(j - <span class="hljs-number">1</span>))&#123;
                    dp[i][j] = dp[i - <span class="hljs-number">1</span>][j - <span class="hljs-number">1</span>];
                &#125; <span class="hljs-keyword">else</span>&#123;
                    dp[i][j] = minHelper(dp[i][j - <span class="hljs-number">1</span>] + <span class="hljs-number">1</span>, dp[i - <span class="hljs-number">1</span>][j] + <span class="hljs-number">1</span>, dp[i - <span class="hljs-number">1</span>][j - <span class="hljs-number">1</span>] + <span class="hljs-number">1</span>);
                &#125;
            &#125;
        &#125;
        
        <span class="hljs-keyword">return</span> dp[al][bl];
    &#125;
    <span class="hljs-function"><span class="hljs-keyword">public</span> <span class="hljs-keyword">int</span> <span class="hljs-title">minHelper</span><span class="hljs-params">(<span class="hljs-keyword">int</span> a, <span class="hljs-keyword">int</span> b, <span class="hljs-keyword">int</span> c)</span></span>&#123;
        <span class="hljs-keyword">return</span> Math.min(a, Math.min(b, c));
    &#125;
&#125;</code></pre>
<h2 id="14-最长公共前缀"><a href="#14-最长公共前缀" class="headerlink" title="14-最长公共前缀"></a>14-最长公共前缀</h2><p>编写一个函数来查找字符串数组中的最长公共前缀。</p>
<p>如果不存在公共前缀，返回空字符串 <code>&quot;&quot;</code>。</p>
 <pre><code class="hljs java"><span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">Solution</span> </span>&#123;
    <span class="hljs-function"><span class="hljs-keyword">public</span> String <span class="hljs-title">longestCommonPrefix</span><span class="hljs-params">(String[] strs)</span> </span>&#123;
        <span class="hljs-keyword">if</span> (strs.length == <span class="hljs-number">0</span>) <span class="hljs-keyword">return</span> <span class="hljs-string">&quot;&quot;</span>;
        <span class="hljs-keyword">int</span> minLen = Integer.MAX_VALUE;
        <span class="hljs-comment">//从字符串数组中找出最小长度的字符串</span>
        <span class="hljs-keyword">for</span> (String str : strs)&#123;
            minLen = Math.min(str.length(), minLen);
        &#125;
        <span class="hljs-keyword">for</span> (<span class="hljs-keyword">int</span> i = <span class="hljs-number">0</span>; i &lt; minLen; i++)&#123;
            <span class="hljs-keyword">for</span> (String str : strs)&#123;
                <span class="hljs-comment">//和第一个比较即可</span>
                <span class="hljs-keyword">if</span> (str.charAt(i) != strs[<span class="hljs-number">0</span>].charAt(i))&#123;
                    <span class="hljs-keyword">return</span> str.substring(<span class="hljs-number">0</span>, i);
                &#125;
            &#125;
        &#125;
        <span class="hljs-keyword">return</span> strs[<span class="hljs-number">0</span>].substring(<span class="hljs-number">0</span>, minLen);
    &#125;
&#125;</code></pre>
<h2 id="402-移掉K位数字"><a href="#402-移掉K位数字" class="headerlink" title="402-移掉K位数字"></a>402-移掉K位数字</h2><p>给定一个以字符串表示的非负整数 <em>num</em>，移除这个数中的 <em>k</em> 位数字，使得剩下的数字最小。</p>
<img src="/2021/05/03/TX%E7%AC%94%E8%AF%95/image-20210330110742505.png" srcset="/img/loading.gif" class="">
<p><code>单调栈</code>——两个<strong>相同位数</strong>的数字大小关系取决于第一个不同的数的大小</p>
<pre><code class="hljs java"><span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">Solution</span> </span>&#123;
    <span class="hljs-function"><span class="hljs-keyword">public</span> String <span class="hljs-title">removeKdigits</span><span class="hljs-params">(String num, <span class="hljs-keyword">int</span> k)</span> </span>&#123;
        <span class="hljs-keyword">if</span> (num.length() == k) <span class="hljs-keyword">return</span> <span class="hljs-string">&quot;0&quot;</span>;
        <span class="hljs-keyword">char</span>[] chars = num.toCharArray();
        Deque&lt;Character&gt; stk = <span class="hljs-keyword">new</span> ArrayDeque&lt;&gt;();
        <span class="hljs-comment">//遍历字符串</span>
        <span class="hljs-keyword">for</span> (<span class="hljs-keyword">char</span> c : chars)&#123;
            <span class="hljs-comment">//需要(栈顶元素比当前元素大，贪心)且能够抛弃(栈stk不空，k &gt; 0)前面的元素</span>
            <span class="hljs-keyword">while</span> (k &gt; <span class="hljs-number">0</span> &amp;&amp; !stk.isEmpty() &amp;&amp; c &lt; stk.peek())&#123;
                stk.pop();
                k--;
            &#125;
            stk.push(c);
        &#125;
        <span class="hljs-comment">//如果num中的字符本来就是递增序列，那么就不会pop元素，则从后面开始删除k位数字</span>
        <span class="hljs-keyword">while</span> (k &gt; <span class="hljs-number">0</span>)&#123;
            stk.pop();
            k--;
        &#125;

        StringBuilder sb = <span class="hljs-keyword">new</span> StringBuilder();
        <span class="hljs-comment">//boolean flag，首零标志</span>
        <span class="hljs-keyword">boolean</span> flag = <span class="hljs-keyword">true</span>;

        <span class="hljs-comment">//已经删除了k位数字，则此时让栈pollLast()</span>
        <span class="hljs-keyword">while</span> (!stk.isEmpty())&#123;
            <span class="hljs-comment">//拿出栈底元素</span>
            <span class="hljs-keyword">char</span> digit = stk.pollLast();
            <span class="hljs-comment">//跳过首零数字</span>
            <span class="hljs-keyword">if</span> (flag &amp;&amp; digit == <span class="hljs-string">&#x27;0&#x27;</span>)&#123;
                <span class="hljs-keyword">continue</span>;
            &#125;
            flag = <span class="hljs-keyword">false</span>;
            sb.append(digit);
        &#125;
        <span class="hljs-comment">//考虑字符串&quot;0&quot;</span>
        <span class="hljs-keyword">return</span> sb.length() == <span class="hljs-number">0</span> ? <span class="hljs-string">&quot;0&quot;</span> : sb.toString();

    &#125;
&#125;</code></pre>
<p><code>如果题目改成求删除 k 个字符之后的最大数，我们只需要将 c &lt; stk.peek() 中的小于号改成大于号即可</code></p>
<h2 id="321-拼接最大数"><a href="#321-拼接最大数" class="headerlink" title="321-拼接最大数"></a>321-拼接最大数</h2><p>给定长度分别为 m 和 n 的两个数组，其元素由 0-9 构成，表示两个自然数各位上的数字。现在从这两个数组中选出 k (k &lt;= m + n) 个数字拼接成一个新的数，要求从同一个数组中<code>取出的数字保持其在原数组中的相对顺序</code>。</p>
<p>求满足该条件的最大数。结果返回一个表示该最大数的长度为 k 的数组。</p>
<p>说明: 请尽可能地优化你算法的时间和空间复杂度。</p>
<img src="/2021/05/03/TX%E7%AC%94%E8%AF%95/image-20210330111855102.png" srcset="/img/loading.gif" class="">
<p><code>单调栈 + 分治</code></p>
<pre><code class="hljs java"><span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">Solution</span> </span>&#123;
    <span class="hljs-keyword">public</span> <span class="hljs-keyword">int</span>[] maxNumber(<span class="hljs-keyword">int</span>[] nums1, <span class="hljs-keyword">int</span>[] nums2, <span class="hljs-keyword">int</span> k) &#123;
        <span class="hljs-keyword">int</span> len1 = nums1.length, len2 = nums2.length;
        <span class="hljs-comment">//两个数组中有一个为空，则转化为一个数组的情况，此时结果不需要融合</span>
        <span class="hljs-keyword">if</span>(nums1 == <span class="hljs-keyword">null</span> || (len1 == <span class="hljs-number">0</span>)) <span class="hljs-keyword">return</span> removeDigits(nums2, k);
        <span class="hljs-keyword">if</span>(nums2 == <span class="hljs-keyword">null</span> || (len2 == <span class="hljs-number">0</span>)) <span class="hljs-keyword">return</span> removeDigits(nums1, k);
        
        <span class="hljs-comment">//len2 &gt; k,</span>
        <span class="hljs-keyword">int</span> i = Math.max(<span class="hljs-number">0</span>, k - len2);
        <span class="hljs-keyword">int</span> maxNum = Integer.MIN_VALUE;


        <span class="hljs-comment">//存储最后的结果数组</span>
        <span class="hljs-keyword">int</span>[] res = <span class="hljs-keyword">null</span>;

        <span class="hljs-comment">//得到取数的组合</span>
        <span class="hljs-keyword">for</span> (; i &lt;= Math.min(len1, k); i++)&#123;
            <span class="hljs-comment">//分别获取两个数组的&quot;最大数&quot;子数组</span>
            <span class="hljs-keyword">int</span>[] res1 = removeDigits(nums1, i);
            <span class="hljs-keyword">int</span>[] res2 = removeDigits(nums2, k - i);
            <span class="hljs-keyword">int</span>[] total = merge(res1, res2);
        
            res = res == <span class="hljs-keyword">null</span> || compare(res, <span class="hljs-number">0</span>, total, <span class="hljs-number">0</span>) &lt; <span class="hljs-number">0</span> ? total : res;
            
        &#125;
        <span class="hljs-keyword">return</span> res;
    &#125;


    <span class="hljs-keyword">public</span> <span class="hljs-keyword">int</span>[] removeDigits(<span class="hljs-keyword">int</span>[] nums, <span class="hljs-keyword">int</span> k)&#123;
        <span class="hljs-keyword">int</span> n = nums.length;
        <span class="hljs-keyword">int</span>[] arr = <span class="hljs-keyword">new</span> <span class="hljs-keyword">int</span>[k];
        <span class="hljs-comment">//要从数组中移除的元素个数</span>
        k = n - k;
        <span class="hljs-keyword">if</span>(k == <span class="hljs-number">0</span>)  <span class="hljs-keyword">return</span> nums.clone();
        <span class="hljs-keyword">if</span>(k == n)  <span class="hljs-keyword">return</span> <span class="hljs-keyword">new</span> <span class="hljs-keyword">int</span>[<span class="hljs-number">0</span>];

        <span class="hljs-comment">//定义单调栈(递减)</span>
        Deque&lt;Integer&gt; stk = <span class="hljs-keyword">new</span> ArrayDeque&lt;&gt;();
        <span class="hljs-comment">//遍历数组，使用单调栈(减少)从数组中移除n-k个数</span>
        <span class="hljs-keyword">for</span> (<span class="hljs-keyword">int</span> i = <span class="hljs-number">0</span>; i &lt; n; i++)&#123;
            <span class="hljs-keyword">while</span> (!stk.isEmpty() &amp;&amp; k &gt; <span class="hljs-number">0</span> &amp;&amp; nums[i] &gt; stk.peek())&#123;
                stk.pop();
                k--;
            &#125;
            stk.push(nums[i]);
        &#125;

        <span class="hljs-comment">//如果nums中的字符本来就是递减序列，那么就不会pop元素，则从后面开始删除k位数字</span>
        <span class="hljs-keyword">while</span> (k &gt; <span class="hljs-number">0</span>)&#123;
            stk.pop();
            k--;
        &#125;
        
        <span class="hljs-keyword">int</span> cnt = <span class="hljs-number">0</span>;
        <span class="hljs-keyword">while</span> (!stk.isEmpty())&#123;
            arr[cnt++] = stk.pollLast();
        &#125;
        <span class="hljs-keyword">return</span> arr;
    &#125;

    <span class="hljs-comment">//将两个最大数组融合成一个最大数组</span>
    <span class="hljs-keyword">public</span> <span class="hljs-keyword">int</span>[] merge(<span class="hljs-keyword">int</span>[] arr1, <span class="hljs-keyword">int</span>[] arr2)&#123;
        <span class="hljs-keyword">int</span> m = arr1.length, n = arr2.length;
        <span class="hljs-keyword">int</span>[] mergeArr = <span class="hljs-keyword">new</span> <span class="hljs-keyword">int</span>[m + n];
        <span class="hljs-keyword">int</span> cnt = <span class="hljs-number">0</span>;
        <span class="hljs-keyword">int</span> p = <span class="hljs-number">0</span>, q = <span class="hljs-number">0</span>;
        <span class="hljs-keyword">while</span> (p &lt; m &amp;&amp; q &lt; n)&#123;
            mergeArr[cnt++] = compare(arr1, p, arr2, q) &gt;= <span class="hljs-number">0</span> ? arr1[p++] : arr2[q++];
        &#125;
        <span class="hljs-keyword">while</span> (p &lt; m)&#123;
            mergeArr[cnt++] = arr1[p++];
        &#125;
        <span class="hljs-keyword">while</span> (q &lt; n)&#123;
            mergeArr[cnt++] = arr2[q++];
        &#125;

        <span class="hljs-keyword">return</span> mergeArr;
    &#125;

    
    <span class="hljs-comment">// 比较 nums1[i,m)  和 nums2[j, n)</span>
    <span class="hljs-comment">// nums1 != null &amp;&amp; nums2 != null</span>
    <span class="hljs-function"><span class="hljs-keyword">private</span> <span class="hljs-keyword">int</span> <span class="hljs-title">compare</span><span class="hljs-params">(<span class="hljs-keyword">int</span>[] nums1, <span class="hljs-keyword">int</span> i, <span class="hljs-keyword">int</span>[] nums2, <span class="hljs-keyword">int</span> j)</span></span>&#123;
        <span class="hljs-keyword">int</span> m = nums1.length;
        <span class="hljs-keyword">int</span> n = nums2.length;

        <span class="hljs-keyword">for</span>(<span class="hljs-keyword">int</span> k=<span class="hljs-number">0</span>, limit = Math.min(m-i, n-j); k &lt; limit; k++)&#123;
            <span class="hljs-keyword">if</span>(nums1[i + k] != nums2[j + k])    <span class="hljs-keyword">return</span> Integer.compare(nums1[i + k], nums2[j + k]);
        &#125;

        <span class="hljs-keyword">return</span> Integer.compare(m - i, n - j); 
    &#125;
&#125;</code></pre>
<h2 id="316-去除重复字母"><a href="#316-去除重复字母" class="headerlink" title="316-去除重复字母"></a>316-去除重复字母</h2><p>给你一个字符串 <code>s</code> ，请你去除字符串中重复的字母，使得每个字母只出现一次。需保证 <code>返回结果的字典序最小</code>（要求不能打乱其他字符的相对位置）。</p>
<p><code>单调栈 + HashSet + 计数数组</code></p>
<img src="/2021/05/03/TX%E7%AC%94%E8%AF%95/image-20210330163459887.png" srcset="/img/loading.gif" class="">
<p><code>图解</code></p>
<img src="/2021/05/03/TX%E7%AC%94%E8%AF%95/image-20210330163446598.png" srcset="/img/loading.gif" class="">
<pre><code class="hljs java"><span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">Solution</span> </span>&#123;
    <span class="hljs-function"><span class="hljs-keyword">public</span> String <span class="hljs-title">removeDuplicateLetters</span><span class="hljs-params">(String s)</span> </span>&#123;
        <span class="hljs-comment">//子序列不重复</span>
        HashSet&lt;Character&gt; set = <span class="hljs-keyword">new</span> HashSet&lt;&gt;();
        <span class="hljs-comment">//使字典序最小</span>
        Deque&lt;Character&gt; stk = <span class="hljs-keyword">new</span> ArrayDeque&lt;&gt;();

        <span class="hljs-comment">//需要对字符串中各个字符计数</span>
        <span class="hljs-keyword">int</span>[] count = <span class="hljs-keyword">new</span> <span class="hljs-keyword">int</span>[<span class="hljs-number">256</span>];
        <span class="hljs-keyword">for</span> (<span class="hljs-keyword">int</span> i = <span class="hljs-number">0</span>; i &lt; s.length(); i++) &#123;
            count[s.charAt(i)]++;
        &#125;

        <span class="hljs-keyword">for</span> (<span class="hljs-keyword">char</span> c : s.toCharArray())&#123;
            <span class="hljs-comment">//当前set中不包含c</span>
            <span class="hljs-keyword">if</span> (!set.contains(c))&#123;
                <span class="hljs-comment">//维护一个单调栈，贪心准则</span>
                <span class="hljs-comment">//pop前需要检查后面还有没有stk.peek()，还有，就pop()，没有，就不能pop。因为需要保证每个字母出现一次</span>
                <span class="hljs-keyword">while</span> (!stk.isEmpty() &amp;&amp; c &lt; stk.peek() &amp;&amp; count[stk.peek()] &gt; <span class="hljs-number">0</span>)&#123;
                    set.remove(stk.pop());
                &#125;
                stk.push(c);
                set.add(c);
            &#125;
            <span class="hljs-comment">//栈中包含c，把相应的计数-1即可</span>
            count[c] -= <span class="hljs-number">1</span>;
        &#125;

        StringBuilder sb = <span class="hljs-keyword">new</span> StringBuilder();
        <span class="hljs-keyword">while</span> (!stk.isEmpty())&#123;
            sb.insert(<span class="hljs-number">0</span>, stk.pop());
        &#125;
        <span class="hljs-keyword">return</span> sb.toString();
    &#125;
&#125;</code></pre>
<h2 id="1081-不同字符的最小子序列"><a href="#1081-不同字符的最小子序列" class="headerlink" title="1081-不同字符的最小子序列"></a>1081-不同字符的最小子序列</h2><p>返回 <code>s</code> 字典序最小的子序列，该子序列包含 <code>s</code> 的所有不同字符，且只包含一次。</p>
<p><code>同上题</code></p>
<pre><code class="hljs java"><span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">Solution</span> </span>&#123;
    <span class="hljs-function"><span class="hljs-keyword">public</span> String <span class="hljs-title">smallestSubsequence</span><span class="hljs-params">(String s)</span> </span>&#123;
        Deque&lt;Character&gt; stk = <span class="hljs-keyword">new</span> ArrayDeque&lt;&gt;();
        HashSet&lt;Character&gt; set = <span class="hljs-keyword">new</span> HashSet&lt;&gt;();

        <span class="hljs-keyword">int</span>[] count = <span class="hljs-keyword">new</span> <span class="hljs-keyword">int</span>[<span class="hljs-number">256</span>];
        <span class="hljs-keyword">for</span> (<span class="hljs-keyword">char</span> c : s.toCharArray())&#123;
            count[c]++;
        &#125;

        <span class="hljs-keyword">for</span> (<span class="hljs-keyword">char</span> c : s.toCharArray())&#123;
            <span class="hljs-keyword">if</span> (!set.contains(c))&#123;
                <span class="hljs-keyword">while</span> (!stk.isEmpty() &amp;&amp; c &lt; stk.peek() &amp;&amp; count[stk.peek()] &gt; <span class="hljs-number">0</span>)&#123;
                    set.remove(stk.pop());
                &#125;
                set.add(c);
                stk.push(c);
            &#125;
            count[c] -= <span class="hljs-number">1</span>;
        &#125;

        StringBuilder sb = <span class="hljs-keyword">new</span> StringBuilder();
        <span class="hljs-keyword">while</span> (!stk.isEmpty())&#123;
            sb.append(stk.pop());
        &#125;
        
        <span class="hljs-keyword">return</span> sb.reverse().toString();

    &#125;
&#125;</code></pre>
<h2 id="543-二叉树的直径"><a href="#543-二叉树的直径" class="headerlink" title="543-二叉树的直径"></a>543-二叉树的直径</h2><p>给定一棵二叉树，你需要计算它的直径长度。一棵二叉树的直径长度是<code>任意两个结点路径长度中的最大值</code>。这条路径可能穿过也可能不穿过根结点。</p>
<p><code>二叉树的直径==树中任意两个节点之间的最大边数==最大的左右子树高度和</code></p>
<pre><code class="hljs java"><span class="hljs-comment">/**</span>
<span class="hljs-comment"> * Definition for a binary tree node.</span>
<span class="hljs-comment"> * public class TreeNode &#123;</span>
<span class="hljs-comment"> *     int val;</span>
<span class="hljs-comment"> *     TreeNode left;</span>
<span class="hljs-comment"> *     TreeNode right;</span>
<span class="hljs-comment"> *     TreeNode() &#123;&#125;</span>
<span class="hljs-comment"> *     TreeNode(int val) &#123; this.val = val; &#125;</span>
<span class="hljs-comment"> *     TreeNode(int val, TreeNode left, TreeNode right) &#123;</span>
<span class="hljs-comment"> *         this.val = val;</span>
<span class="hljs-comment"> *         this.left = left;</span>
<span class="hljs-comment"> *         this.right = right;</span>
<span class="hljs-comment"> *     &#125;</span>
<span class="hljs-comment"> * &#125;</span>
<span class="hljs-comment"> */</span>
<span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">Solution</span> </span>&#123;
    <span class="hljs-keyword">int</span> res = <span class="hljs-number">0</span>;
    <span class="hljs-function"><span class="hljs-keyword">public</span> <span class="hljs-keyword">int</span> <span class="hljs-title">diameterOfBinaryTree</span><span class="hljs-params">(TreeNode root)</span> </span>&#123;
        getHeight(root);
        <span class="hljs-keyword">return</span> res;
    &#125;

    <span class="hljs-function"><span class="hljs-keyword">public</span> <span class="hljs-keyword">int</span> <span class="hljs-title">getHeight</span><span class="hljs-params">(TreeNode node)</span></span>&#123;
        <span class="hljs-keyword">if</span> (node == <span class="hljs-keyword">null</span>) <span class="hljs-keyword">return</span> <span class="hljs-number">0</span>;
        <span class="hljs-keyword">int</span> lHeight = getHeight(node.left);
        <span class="hljs-keyword">int</span> rHeight = getHeight(node.right);
        res = Math.max(res, lHeight + rHeight);
        <span class="hljs-keyword">return</span> <span class="hljs-number">1</span> + Math.max(lHeight, rHeight);
    &#125;
&#125;</code></pre>
<h2 id="78-子集"><a href="#78-子集" class="headerlink" title="78-子集"></a>78-子集</h2><p>给你一个整数数组 <code>nums</code> ，数组中的<code>元素互不相同</code>。返回该数组所有可能的子集（幂集）。</p>
<p>解集 <strong>不能</strong> 包含重复的子集。你可以按 <strong>任意顺序</strong> 返回解集。</p>
<img src="/2021/05/03/TX%E7%AC%94%E8%AF%95/image-20210401101102627.png" srcset="/img/loading.gif" class="">
<p><code>回溯法</code>—— 按子集的不同大小（0 ~ n）分别进行回溯</p>
 <pre><code class="hljs java"><span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">Solution</span> </span>&#123;
    <span class="hljs-keyword">int</span> n, k;
    List&lt;List&lt;Integer&gt;&gt; res = <span class="hljs-keyword">new</span> ArrayList&lt;&gt;();
    <span class="hljs-keyword">public</span> List&lt;List&lt;Integer&gt;&gt; subsets(<span class="hljs-keyword">int</span>[] nums) &#123;
        n = nums.length;
        <span class="hljs-comment">//子集中元素个数在0 ~ n之间</span>
        <span class="hljs-keyword">for</span> (k = <span class="hljs-number">0</span>; k &lt; n + <span class="hljs-number">1</span>; k++)&#123;
            backTrack(<span class="hljs-keyword">new</span> ArrayList&lt;Integer&gt;(), nums, <span class="hljs-number">0</span>);
        &#125;
        <span class="hljs-keyword">return</span> res;
    &#125;

    <span class="hljs-function"><span class="hljs-keyword">public</span> <span class="hljs-keyword">void</span> <span class="hljs-title">backTrack</span><span class="hljs-params">(ArrayList&lt;Integer&gt; cur, <span class="hljs-keyword">int</span>[] arr, <span class="hljs-keyword">int</span> size)</span></span>&#123;
        <span class="hljs-keyword">if</span> (cur.size() == k)&#123;
            res.add(<span class="hljs-keyword">new</span> ArrayList(cur));
            <span class="hljs-keyword">return</span>;
        &#125;
        <span class="hljs-keyword">for</span> (<span class="hljs-keyword">int</span> i = size; i &lt; n; i++)&#123;
            <span class="hljs-comment">//选择当前元素</span>
            cur.add(arr[i]);
            <span class="hljs-comment">//继续回溯</span>
            backTrack(cur, arr, i + <span class="hljs-number">1</span>);
            <span class="hljs-comment">//撤销选择</span>
            cur.remove(cur.size() - <span class="hljs-number">1</span>);
        &#125;
    &#125;
&#125;</code></pre>
<h2 id="90-子集Ⅱ"><a href="#90-子集Ⅱ" class="headerlink" title="90-子集Ⅱ"></a>90-子集Ⅱ</h2><p>给你一个整数数组 nums ，其中<code>可能包含重复元素</code>，请你返回该数组所有可能的子集（幂集）。</p>
<p><code>解集不能包含重复</code>的子集。返回的解集中，子集可以按 任意顺序 排列。</p>
<p><code>回溯 + 排序(剪枝)</code></p>
<pre><code class="hljs java"><span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">Solution</span> </span>&#123;
    <span class="hljs-keyword">int</span> n, k;
    List&lt;List&lt;Integer&gt;&gt; res = <span class="hljs-keyword">new</span> ArrayList&lt;&gt;();
    <span class="hljs-keyword">public</span> List&lt;List&lt;Integer&gt;&gt; subsetsWithDup(<span class="hljs-keyword">int</span>[] nums) &#123;
        n = nums.length;
        <span class="hljs-comment">//先排序，方便剪枝</span>
        Arrays.sort(nums);
        <span class="hljs-keyword">for</span> (k = <span class="hljs-number">0</span>; k &lt; n + <span class="hljs-number">1</span>; k++)&#123;
            backTrack(<span class="hljs-keyword">new</span> ArrayList&lt;Integer&gt;(), nums, <span class="hljs-number">0</span>);
        &#125;
        <span class="hljs-keyword">return</span> res;
    &#125;

    <span class="hljs-function"><span class="hljs-keyword">public</span> <span class="hljs-keyword">void</span> <span class="hljs-title">backTrack</span><span class="hljs-params">(ArrayList&lt;Integer&gt; cur, <span class="hljs-keyword">int</span>[] arr, <span class="hljs-keyword">int</span> size)</span></span>&#123;
        <span class="hljs-keyword">if</span> (cur.size() == k)&#123;
            res.add(<span class="hljs-keyword">new</span> ArrayList(cur));
            <span class="hljs-keyword">return</span>;
        &#125;
        <span class="hljs-keyword">for</span> (<span class="hljs-keyword">int</span> i = size; i &lt; n; i++)&#123;
            <span class="hljs-comment">//剪枝, i大于size且当前待选的元素和前一个已选的一样，此时才需要剪枝</span>
            <span class="hljs-keyword">if</span> (i &gt; size &amp;&amp; arr[i] == arr[i - <span class="hljs-number">1</span>]) <span class="hljs-keyword">continue</span>;
            <span class="hljs-comment">//做选择</span>
            cur.add(arr[i]);
            <span class="hljs-comment">//继续回溯</span>
            backTrack(cur, arr, i + <span class="hljs-number">1</span>);
            <span class="hljs-comment">//撤销选择</span>
            cur.remove(cur.size() - <span class="hljs-number">1</span>);
        &#125;
    &#125;
&#125;</code></pre>
<h2 id="7-整数反转"><a href="#7-整数反转" class="headerlink" title="7-整数反转"></a>7-整数反转</h2><p>给你一个 32 位的有符号整数 x ，返回将 x 中的数字部分反转后的结果。</p>
<p><code>如果反转后整数超过 32 位的有符号整数的范围 [−231,  231 − 1] ，就返回 0。</code></p>
<p>假设环境不允许存储 64 位整数（有符号或无符号）。</p>
<pre><code class="hljs java"><span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">Solution</span> </span>&#123;
    <span class="hljs-function"><span class="hljs-keyword">public</span> <span class="hljs-keyword">int</span> <span class="hljs-title">reverse</span><span class="hljs-params">(<span class="hljs-keyword">int</span> x)</span> </span>&#123;
        <span class="hljs-keyword">long</span> sum = <span class="hljs-number">0</span>;
        <span class="hljs-keyword">while</span> (x != <span class="hljs-number">0</span>)&#123;
            sum = sum * <span class="hljs-number">10</span> + x % <span class="hljs-number">10</span>;
            x /= <span class="hljs-number">10</span>;
        &#125;
        <span class="hljs-comment">//越界判断</span>
        <span class="hljs-keyword">return</span> sum &gt; Integer.MAX_VALUE || sum &lt; Integer.MIN_VALUE ? <span class="hljs-number">0</span> : (<span class="hljs-keyword">int</span>)sum;
    &#125;
&#125;</code></pre>
<h2 id="322-零钱兑换"><a href="#322-零钱兑换" class="headerlink" title="322-零钱兑换"></a>322-零钱兑换</h2><p>给定不同面额的硬币 coins 和一个总金额 amount。编写一个函数来计算可以凑成总金额所需的最少的硬币个数。如果没有任何一种硬币组合能组成总金额，返回 -1。</p>
<p>你可以认为每种硬币的数量是无限的。</p>
<p><code>动态规划</code></p>
<pre><code class="hljs java"><span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">Solution</span> </span>&#123;
    <span class="hljs-function"><span class="hljs-keyword">public</span> <span class="hljs-keyword">int</span> <span class="hljs-title">coinChange</span><span class="hljs-params">(<span class="hljs-keyword">int</span>[] coins, <span class="hljs-keyword">int</span> amount)</span> </span>&#123;
        <span class="hljs-keyword">int</span> n = coins.length;
        <span class="hljs-keyword">int</span>[] dp = <span class="hljs-keyword">new</span> <span class="hljs-keyword">int</span>[amount + <span class="hljs-number">1</span>];
        <span class="hljs-comment">//初始化</span>
        Arrays.fill(dp, amount + <span class="hljs-number">1</span>);
        <span class="hljs-comment">//dp[amount]代表为了凑齐总金额amount需要的硬币组合的最少个数</span>
        <span class="hljs-comment">//base case</span>
        dp[<span class="hljs-number">0</span>] = <span class="hljs-number">0</span>;
        <span class="hljs-keyword">for</span> (<span class="hljs-keyword">int</span> i = <span class="hljs-number">0</span>; i &lt;= amount; i++)&#123;
            <span class="hljs-keyword">for</span> (<span class="hljs-keyword">int</span> coin : coins)&#123;
                <span class="hljs-comment">//子问题无解，跳过</span>
                <span class="hljs-keyword">if</span> (i - coin &lt; <span class="hljs-number">0</span>) <span class="hljs-keyword">continue</span>;
                <span class="hljs-comment">//状态更新：dp[amount] = 1 + Math.min(dp[amount - coins[0]], dp[amount - coins[1],...)</span>
                dp[i] = Math.min(dp[i], <span class="hljs-number">1</span> + dp[i - coin]);
            &#125;
            
        &#125;
        <span class="hljs-comment">//判断有无解再返回，dp[amount] == amount</span>
        <span class="hljs-keyword">return</span> dp[amount] == amount + <span class="hljs-number">1</span> ? -<span class="hljs-number">1</span> : dp[amount];
    &#125;
&#125;</code></pre>
<p><code>dp</code>数组初始化为<code>amount + 1</code>呢，因为凑成<code>amount</code>金额的硬币数最多只可能等于<code>amount</code>（全用 1 元面值的硬币），所以初始化为<code>amount + 1</code>就<code>相当于初始化为正无穷</code>，便于后续取最小值。</p>
<h2 id="518-零钱兑换Ⅱ"><a href="#518-零钱兑换Ⅱ" class="headerlink" title="518-零钱兑换Ⅱ"></a>518-零钱兑换Ⅱ</h2><p>给定不同面额的硬币和一个总金额。写出函数来计算可以凑成总金额的硬币组合数。假设每一种面额的硬币有无限个。 </p>
<img src="/2021/05/03/TX%E7%AC%94%E8%AF%95/image-20210401144034823.png" srcset="/img/loading.gif" class="">
<p><code>完全背包</code> —— <code>dp[i][j]</code>代表若只使用前<code>i</code>个物品，当背包容量为<code>j</code>时，有<code>dp[i][j]</code>种方法可以装满背包</p>
<p><code>状态转移</code>—— <code>dp[i][j] = dp[i - 1][j] + dp[i][j - coins[i - 1]]</code></p>
<p><code>目标</code> —— <code>dp[coins.length][amount]</code></p>
<pre><code class="hljs java"><span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">Solution</span> </span>&#123;
    <span class="hljs-function"><span class="hljs-keyword">public</span> <span class="hljs-keyword">int</span> <span class="hljs-title">change</span><span class="hljs-params">(<span class="hljs-keyword">int</span> amount, <span class="hljs-keyword">int</span>[] coins)</span> </span>&#123;
        <span class="hljs-keyword">int</span> n = coins.length;
        <span class="hljs-keyword">int</span>[][] dp = <span class="hljs-keyword">new</span> <span class="hljs-keyword">int</span>[n + <span class="hljs-number">1</span>][amount + <span class="hljs-number">1</span>];
        <span class="hljs-comment">// base case</span>
        <span class="hljs-keyword">for</span> (<span class="hljs-keyword">int</span> i = <span class="hljs-number">0</span>; i &lt;= n; i++) 
            dp[i][<span class="hljs-number">0</span>] = <span class="hljs-number">1</span>;

        <span class="hljs-keyword">for</span> (<span class="hljs-keyword">int</span> i = <span class="hljs-number">1</span>; i &lt;= n; i++) &#123;
            <span class="hljs-keyword">for</span> (<span class="hljs-keyword">int</span> j = <span class="hljs-number">1</span>; j &lt;= amount; j++)
                <span class="hljs-keyword">if</span> (j - coins[i-<span class="hljs-number">1</span>] &gt;= <span class="hljs-number">0</span>)
                    <span class="hljs-comment">//将第i个物品coins[i - 1]不装背包和装背包</span>
                    dp[i][j] = dp[i - <span class="hljs-number">1</span>][j] + dp[i][j - coins[i-<span class="hljs-number">1</span>]];
                <span class="hljs-keyword">else</span> 
                    dp[i][j] = dp[i - <span class="hljs-number">1</span>][j];
        &#125;
        <span class="hljs-keyword">return</span> dp[n][amount];
    &#125;
&#125;</code></pre>
<p><code>状态压缩</code>——<code>dp</code>数组的转移只和<code>dp[i][..]</code>和<code>dp[i-1][..]</code>有关，所以可以压缩状态</p>
<p><code>状态转移</code> —— <code>dp[j] = dp[j] + dp[j - coin]</code></p>
<pre><code class="hljs java"><span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">Solution</span> </span>&#123;
    <span class="hljs-function"><span class="hljs-keyword">public</span> <span class="hljs-keyword">int</span> <span class="hljs-title">change</span><span class="hljs-params">(<span class="hljs-keyword">int</span> amount, <span class="hljs-keyword">int</span>[] coins)</span> </span>&#123;
        <span class="hljs-comment">//dp[amount]代表用coins中的硬币凑成总金额为amount的方法数</span>
        <span class="hljs-keyword">int</span>[] dp = <span class="hljs-keyword">new</span> <span class="hljs-keyword">int</span>[amount + <span class="hljs-number">1</span>];

        <span class="hljs-comment">//base case，装满容量为0的背包的方法，什么都不装，就是1</span>
        dp[<span class="hljs-number">0</span>] = <span class="hljs-number">1</span>;
        <span class="hljs-comment">//对于硬币数组中得硬币，我们必须使用第k个硬币的时候，当前金额的组合数</span>
        <span class="hljs-keyword">for</span> (<span class="hljs-keyword">int</span> coin : coins)&#123;
            <span class="hljs-keyword">for</span> (<span class="hljs-keyword">int</span> j = coin; j &lt;= amount; j++)&#123;
                <span class="hljs-comment">//dp[amount] += dp[amount - coin]</span>
                dp[j] += dp[j - coin];
            &#125;
        &#125;
        <span class="hljs-keyword">return</span> dp[amount];

    &#125;
&#125;</code></pre>

            </div>
            <hr>
            <div>
              <div class="post-metas mb-3">
                
                  <div class="post-meta mr-3">
                    <i class="iconfont icon-category"></i>
                    
                      <a class="hover-with-bg" href="/categories/%E7%AE%97%E6%B3%95/">算法</a>
                    
                  </div>
                
                
                  <div class="post-meta">
                    <i class="iconfont icon-tags"></i>
                    
                      <a class="hover-with-bg" href="/tags/%E7%AC%94%E8%AF%95%E9%A2%98/">笔试题</a>
                    
                  </div>
                
              </div>
              
                <p class="note note-warning">本博客所有文章除特别声明外，均采用 <a target="_blank" href="https://creativecommons.org/licenses/by-sa/4.0/deed.zh" rel="nofollow noopener noopener">CC BY-SA 4.0 协议</a> ，转载请注明出处！</p>
              
              
                <div class="post-prevnext row">
                  <article class="post-prev col-6">
                    
                    
                      <a href="/2021/05/28/Docker-Desktop-Installation-On-Windows/">
                        <i class="iconfont icon-arrowleft"></i>
                        <span class="hidden-mobile">Docker-Desktop-Installation-On-Windows</span>
                        <span class="visible-mobile">上一篇</span>
                      </a>
                    
                  </article>
                  <article class="post-next col-6">
                    
                    
                      <a href="/2021/05/03/%E6%89%8B%E6%92%95%E6%8E%92%E5%BA%8F%E7%AE%97%E6%B3%95/">
                        <span class="hidden-mobile">手撕排序算法</span>
                        <span class="visible-mobile">下一篇</span>
                        <i class="iconfont icon-arrowright"></i>
                      </a>
                    
                  </article>
                </div>
              
            </div>

            
          </article>
        </div>
      </div>
    </div>
    
      <div class="d-none d-lg-block col-lg-2 toc-container" id="toc-ctn">
        <div id="toc">
  <p class="toc-header"><i class="iconfont icon-list"></i>&nbsp;目录</p>
  <div id="tocbot"></div>
</div>

      </div>
    
  </div>
</div>

<!-- Custom -->


    
  </main>

  
    <a id="scroll-top-button" href="#" role="button">
      <i class="iconfont icon-arrowup" aria-hidden="true"></i>
    </a>
  

  
    <div class="modal fade" id="modalSearch" tabindex="-1" role="dialog" aria-labelledby="ModalLabel"
     aria-hidden="true">
  <div class="modal-dialog modal-dialog-scrollable modal-lg" role="document">
    <div class="modal-content">
      <div class="modal-header text-center">
        <h4 class="modal-title w-100 font-weight-bold">搜索</h4>
        <button type="button" id="local-search-close" class="close" data-dismiss="modal" aria-label="Close">
          <span aria-hidden="true">&times;</span>
        </button>
      </div>
      <div class="modal-body mx-3">
        <div class="md-form mb-5">
          <input type="text" id="local-search-input" class="form-control validate">
          <label data-error="x" data-success="v"
                 for="local-search-input">关键词</label>
        </div>
        <div class="list-group" id="local-search-result"></div>
      </div>
    </div>
  </div>
</div>
  

  

  <footer class="text-center mt-5 py-3">
  <div class="footer-content">
     <a href="https://hexo.io" target="_blank" rel="nofollow noopener"><span>Hexo</span></a> <i class="iconfont icon-love"></i> <a href="https://github.com/fluid-dev/hexo-theme-fluid" target="_blank" rel="nofollow noopener"><span>Fluid</span></a> 
  </div>
  

  

  
</footer>

<!-- SCRIPTS -->
<script  src="https://cdn.staticfile.org/jquery/3.4.1/jquery.min.js" ></script>
<script  src="https://cdn.staticfile.org/twitter-bootstrap/4.4.1/js/bootstrap.min.js" ></script>
<script  src="/js/debouncer.js" ></script>
<script  src="/js/main.js" ></script>

<!-- Plugins -->


  
    <script  src="/js/lazyload.js" ></script>
  



  



  <script defer src="https://cdn.staticfile.org/clipboard.js/2.0.6/clipboard.min.js" ></script>
  <script  src="/js/clipboard-use.js" ></script>



  <script defer src="https://busuanzi.ibruce.info/busuanzi/2.3/busuanzi.pure.mini.js" ></script>





  <script  src="https://cdn.staticfile.org/tocbot/4.11.1/tocbot.min.js" ></script>
  <script>
    $(document).ready(function () {
      var boardCtn = $('#board-ctn');
      var boardTop = boardCtn.offset().top;

      tocbot.init({
        tocSelector: '#tocbot',
        contentSelector: '#post-body',
        headingSelector: 'h1,h2,h3,h4,h5,h6',
        linkClass: 'tocbot-link',
        activeLinkClass: 'tocbot-active-link',
        listClass: 'tocbot-list',
        isCollapsedClass: 'tocbot-is-collapsed',
        collapsibleClass: 'tocbot-is-collapsible',
        collapseDepth: 0,
        scrollSmooth: true,
        headingsOffset: -boardTop
      });
      if ($('.toc-list-item').length > 0) {
        $('#toc').css('visibility', 'visible');
      }
    });
  </script>



  <script  src="https://cdn.staticfile.org/typed.js/2.0.11/typed.min.js" ></script>
  <script>
    var typed = new Typed('#subtitle', {
      strings: [
        '  ',
        "TX笔试&nbsp;",
      ],
      cursorChar: "_",
      typeSpeed: 70,
      loop: false,
    });
    typed.stop();
    $(document).ready(function () {
      $(".typed-cursor").addClass("h2");
      typed.start();
    });
  </script>



  <script  src="https://cdn.staticfile.org/anchor-js/4.2.2/anchor.min.js" ></script>
  <script>
    anchors.options = {
      placement: "right",
      visible: "hover",
      
    };
    var el = "h1,h2,h3,h4,h5,h6".split(",");
    var res = [];
    for (item of el) {
      res.push(".markdown-body > " + item)
    }
    anchors.add(res.join(", "))
  </script>



  <script  src="/js/local-search.js" ></script>
  <script>
    var path = "/local-search.xml";
    var inputArea = document.querySelector("#local-search-input");
    inputArea.onclick = function () {
      searchFunc(path, 'local-search-input', 'local-search-result');
      this.onclick = null
    }
  </script>



  <script  src="https://cdn.staticfile.org/fancybox/3.5.7/jquery.fancybox.min.js" ></script>
  <link  rel="stylesheet" href="https://cdn.staticfile.org/fancybox/3.5.7/jquery.fancybox.min.css" />

  <script>
    $('#post img:not(.no-zoom img, img[no-zoom]), img[zoom]').each(
      function () {
        var element = document.createElement('a');
        $(element).attr('data-fancybox', 'images');
        $(element).attr('href', $(this).attr('src'));
        $(this).wrap(element);
      }
    );
  </script>





  

  
    <!-- MathJax -->
    <script>
      MathJax = {
        tex: {
          inlineMath: [['$', '$'], ['\\(', '\\)']]
        },
        options: {
          renderActions: {
            findScript: [10, doc => {
              document.querySelectorAll('script[type^="math/tex"]').forEach(node => {
                const display = !!node.type.match(/; *mode=display/);
                const math = new doc.options.MathItem(node.textContent, doc.inputJax[0], display);
                const text = document.createTextNode('');
                node.parentNode.replaceChild(text, node);
                math.start = { node: text, delim: '', n: 0 };
                math.end = { node: text, delim: '', n: 0 };
                doc.math.push(math);
              });
            }, '', false],
            insertedScript: [200, () => {
              document.querySelectorAll('mjx-container').forEach(node => {
                let target = node.parentNode;
                if (target.nodeName.toLowerCase() === 'li') {
                  target.parentNode.classList.add('has-jax');
                }
              });
            }, '', false]
          }
        }
      };
    </script>

    <script async src="https://cdn.staticfile.org/mathjax/3.0.5/es5/tex-svg.js" ></script>

  











</body>
</html>
